KorzinaWindow;orderMethods
This commit is contained in:
parent
86c9b9fd23
commit
e3c4a408b1
@ -17,7 +17,12 @@ 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.CategorySneakersScreen
|
||||||
|
import com.example.testktor.screen.main.FavouriteSneakersContent
|
||||||
|
import com.example.testktor.screen.main.FavouriteSneakersScreen
|
||||||
|
import com.example.testktor.screen.main.KorzinaSneakersContent
|
||||||
|
import com.example.testktor.screen.main.KorzinaSneakersScreen
|
||||||
import com.example.testktor.screen.main.PopularSneakersScreen
|
import com.example.testktor.screen.main.PopularSneakersScreen
|
||||||
|
import com.example.testktor.screen.main.SuccessOrderSneakersScreen
|
||||||
//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
|
||||||
@ -65,6 +70,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
composable("categorySneakers_screen") {
|
composable("categorySneakers_screen") {
|
||||||
CategorySneakersScreen(navController, viewModel)
|
CategorySneakersScreen(navController, viewModel)
|
||||||
}
|
}
|
||||||
|
composable("favouriteSneakers_screen") {
|
||||||
|
FavouriteSneakersScreen(navController, viewModel)
|
||||||
|
}
|
||||||
|
composable("korzinaSneakers_screen") {
|
||||||
|
KorzinaSneakersScreen(navController, viewModel)
|
||||||
|
}
|
||||||
|
composable("successOrderSneakers_screen") {
|
||||||
|
SuccessOrderSneakersScreen(navController, viewModel)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ data class Sneaker(
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class SneakerShop(
|
data class SneakerShop(
|
||||||
val sneaker: Sneaker,
|
val sneaker: Sneaker,
|
||||||
var likeOrNot: Boolean
|
var likeOrNot: Boolean,
|
||||||
|
var orderOrNot: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.example.testktor.ViewModel
|
package com.example.testktor.ViewModel
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -7,8 +8,11 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.example.testktor.BuySneakerRequest
|
||||||
|
import com.example.testktor.BuySneakersRequest
|
||||||
import com.example.testktor.Category
|
import com.example.testktor.Category
|
||||||
import com.example.testktor.SneakerCategoryResponse
|
import com.example.testktor.SneakerCategoryResponse
|
||||||
|
import com.example.testktor.SneakerShop
|
||||||
import com.example.testktor.getSneakers
|
import com.example.testktor.getSneakers
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.client.engine.android.Android
|
import io.ktor.client.engine.android.Android
|
||||||
@ -21,6 +25,9 @@ class MainViewModel : ViewModel() {
|
|||||||
var selectedCategory by mutableStateOf<Category?>(null)
|
var selectedCategory by mutableStateOf<Category?>(null)
|
||||||
|
|
||||||
var likedSneakers = mutableStateMapOf<Int, Boolean>()
|
var likedSneakers = mutableStateMapOf<Int, Boolean>()
|
||||||
|
var orderedSneakers = mutableStateMapOf<Int, Boolean>()
|
||||||
|
|
||||||
|
var sneakerQuantities = mutableStateMapOf<Int, Int>()
|
||||||
|
|
||||||
private val client = HttpClient(Android)
|
private val client = HttpClient(Android)
|
||||||
|
|
||||||
@ -38,6 +45,67 @@ class MainViewModel : ViewModel() {
|
|||||||
return likedSneakers[sneakerId] ?: false
|
return likedSneakers[sneakerId] ?: false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toggleOrder(sneakerId: Int) {
|
||||||
|
orderedSneakers[sneakerId] = !(orderedSneakers[sneakerId] ?: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isOrdered(sneakerId: Int): Boolean {
|
||||||
|
return orderedSneakers[sneakerId] ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setSneakerQuantity(sneakerId: Int, quantity: Int) {
|
||||||
|
sneakerQuantities[sneakerId] = quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSneakerQuantity(sneakerId: Int): Int {
|
||||||
|
return sneakerQuantities[sneakerId] ?: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLikedSneakersByCategory(): List<SneakerShop> {
|
||||||
|
return sneakersCategories.sneakers.filter {
|
||||||
|
likedSneakers[it.id] == true && (selectedCategory == null || it.categoryId == selectedCategory?.id)
|
||||||
|
}.map {
|
||||||
|
SneakerShop(it, likeOrNot = true, orderOrNot = isOrdered(it.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOrderedSneakersByCategory(): List<SneakerShop> {
|
||||||
|
return sneakersCategories.sneakers.filter {
|
||||||
|
orderedSneakers[it.id] == true && (selectedCategory == null || it.categoryId == selectedCategory?.id)
|
||||||
|
}.map {
|
||||||
|
SneakerShop(it, likeOrNot = isLiked(it.id), orderOrNot = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLikedSneakersTotalPrice(): Double {
|
||||||
|
return getOrderedSneakersByCategory().sumOf {
|
||||||
|
(it.sneaker.cost * (sneakerQuantities[it.sneaker.id] ?: 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeSneakerFromCart(id: Int) {
|
||||||
|
orderedSneakers[id] = false
|
||||||
|
sneakerQuantities.remove(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateBuySneakersRequest(): BuySneakersRequest {
|
||||||
|
val orderedSneakersList = getOrderedSneakersByCategory()
|
||||||
|
Log.d("generateBuySneakersRequest", "Кроссовки в заказе: ${orderedSneakersList.size}")
|
||||||
|
val requestList = orderedSneakersList.map {
|
||||||
|
Log.d("generateBuySneakersRequest", "id=${it.sneaker.id}, count=${getSneakerQuantity(it.sneaker.id)}")
|
||||||
|
BuySneakerRequest(
|
||||||
|
sneakerId = it.sneaker.id,
|
||||||
|
count = getSneakerQuantity(it.sneaker.id)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return BuySneakersRequest(sneakers = requestList)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCart() {
|
||||||
|
orderedSneakers.clear()
|
||||||
|
sneakerQuantities.clear()
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshData() {
|
fun refreshData() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList())
|
sneakersCategories = getSneakers(client) ?: SneakerCategoryResponse(emptyList(), emptyList())
|
||||||
|
@ -146,7 +146,7 @@ suspend fun buySneakers(client: HttpClient, order: BuySneakersRequest): Boolean
|
|||||||
headers {
|
headers {
|
||||||
append(HttpHeaders.ContentType, "application/json")
|
append(HttpHeaders.ContentType, "application/json")
|
||||||
}
|
}
|
||||||
setBody(order)
|
setBody(Json.encodeToString(order))
|
||||||
}
|
}
|
||||||
|
|
||||||
val responseBody = response.bodyAsText()
|
val responseBody = response.bodyAsText()
|
||||||
|
@ -62,11 +62,26 @@ fun SneakerCategorySelection(sneakers: List<SneakerShop>, viewModel: MainViewMod
|
|||||||
SneakerButton(
|
SneakerButton(
|
||||||
sneakerShop = sneakerShop,
|
sneakerShop = sneakerShop,
|
||||||
isLiked = viewModel.isLiked(sneakerShop.sneaker.id),
|
isLiked = viewModel.isLiked(sneakerShop.sneaker.id),
|
||||||
onClick = { /* TODO: Действие кнопки */ },
|
isOrdered = viewModel.isOrdered(sneakerShop.sneaker.id),
|
||||||
|
onClick = { /* переход */ },
|
||||||
onFavoriteClick = {
|
onFavoriteClick = {
|
||||||
viewModel.toggleLike(sneakerShop.sneaker.id)
|
viewModel.toggleLike(sneakerShop.sneaker.id)
|
||||||
val likedCount = viewModel.likedSneakers.values.count { it }
|
val likedCount = viewModel.likedSneakers.values.count { it }
|
||||||
Log.d("SneakerLike", "Лайкнуто кроссовок: $likedCount")
|
Log.d("SneakerLike", "Лайкнуто кроссовок: $likedCount")
|
||||||
|
},
|
||||||
|
onOrderClick = {
|
||||||
|
val sneakerId = sneakerShop.sneaker.id
|
||||||
|
|
||||||
|
if (!viewModel.isOrdered(sneakerId)) {
|
||||||
|
viewModel.toggleOrder(sneakerId)
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, 1)
|
||||||
|
} else {
|
||||||
|
viewModel.toggleOrder(sneakerId)
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val orderCount = viewModel.orderedSneakers.values.count { it }
|
||||||
|
Log.d("SneakerOrder", "Добавлено в корзину кроссовок: $orderCount")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
package com.example.testktor.method.main
|
||||||
|
|
@ -0,0 +1,264 @@
|
|||||||
|
package com.example.testktor.method.main
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
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.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.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Delete
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults.buttonColors
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
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.navigation.NavController
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.example.testktor.SneakerShop
|
||||||
|
import com.example.testktor.ViewModel.MainViewModel
|
||||||
|
import com.example.testktor.buySneakers
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.android.Android
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.foundation.Canvas
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BottomKorzinaNavigationBar(
|
||||||
|
navController: NavController,
|
||||||
|
sneakers: List<SneakerShop>,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val client = remember { HttpClient(Android) }
|
||||||
|
|
||||||
|
val totalPrice by remember(sneakers) {
|
||||||
|
derivedStateOf {
|
||||||
|
sneakers.sumOf {
|
||||||
|
it.sneaker.cost * viewModel.getSneakerQuantity(it.sneaker.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val totalPriceWithDelivery by remember(totalPrice) {
|
||||||
|
derivedStateOf { totalPrice + 60 }
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color.LightGray),
|
||||||
|
contentAlignment = Alignment.BottomCenter
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(16.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(text = "Сумма", fontSize = 18.sp)
|
||||||
|
Text(text = "$totalPrice рубликов", fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(text = "Доставка", fontSize = 18.sp)
|
||||||
|
Text(text = "60 рубликов", fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
Canvas(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.height(1.dp)
|
||||||
|
) {
|
||||||
|
val dashWidth = 10f
|
||||||
|
val gapWidth = 10f
|
||||||
|
var currentX = 0f
|
||||||
|
|
||||||
|
while (currentX < size.width) {
|
||||||
|
drawLine(
|
||||||
|
color = Color.Gray,
|
||||||
|
start = Offset(currentX, 0f),
|
||||||
|
end = Offset(currentX + dashWidth, 0f),
|
||||||
|
strokeWidth = 2f
|
||||||
|
)
|
||||||
|
currentX += dashWidth + gapWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 8.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween
|
||||||
|
) {
|
||||||
|
Text(text = "Итого", fontSize = 18.sp)
|
||||||
|
Text(text = "$totalPriceWithDelivery рубликов", fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 16.dp, vertical = 12.dp)
|
||||||
|
.height(50.dp),
|
||||||
|
shape = RoundedCornerShape(10.dp),
|
||||||
|
colors = buttonColors(
|
||||||
|
containerColor = Color(0xFF48B2E7),
|
||||||
|
contentColor = Color.White
|
||||||
|
),
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
val order = viewModel.generateBuySneakersRequest()
|
||||||
|
Log.d("BottomKorzinaNavigationBar", "Order: $order")
|
||||||
|
val success = buySneakers(client, order)
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
viewModel.clearCart()
|
||||||
|
Toast.makeText(context, "Покупка успешно оформлена", Toast.LENGTH_SHORT).show()
|
||||||
|
navController.navigate("successOrderSneakers_screen")
|
||||||
|
} else {
|
||||||
|
Toast.makeText(context, "Ошибка при покупке", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Оформить заказ", fontSize = 16.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SneakerKorzinaButton(
|
||||||
|
sneakerShop: SneakerShop,
|
||||||
|
quantity: Int,
|
||||||
|
onClick: () -> Unit,
|
||||||
|
onIncrease: () -> Unit,
|
||||||
|
onDecrease: () -> Unit,
|
||||||
|
onRemove: () -> Unit
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color(0xFF48B2E7), RoundedCornerShape(8.dp))
|
||||||
|
.padding(4.dp),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onIncrease) {
|
||||||
|
Text("+", color = Color.White, fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
Text("$quantity", color = Color.White, fontSize = 16.sp)
|
||||||
|
IconButton(onClick = onDecrease) {
|
||||||
|
Text("-", color = Color.White, fontSize = 18.sp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = Modifier
|
||||||
|
.width(140.dp)
|
||||||
|
.height(180.dp),
|
||||||
|
colors = 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 = "₽${sneakerShop.sneaker.cost}", fontSize = 15.sp, color = Color.Black)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.background(Color.Red, RoundedCornerShape(8.dp))
|
||||||
|
.size(40.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
IconButton(onClick = onRemove) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Delete,
|
||||||
|
contentDescription = "Удалить",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SneakerKorzinaSelection(sneakers: List<SneakerShop>, viewModel: MainViewModel) {
|
||||||
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
sneakers.chunked(1).forEach { sneakerPair ->
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(vertical = 8.dp),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly
|
||||||
|
) {
|
||||||
|
sneakerPair.forEach { sneakerShop ->
|
||||||
|
val sneakerId = sneakerShop.sneaker.id
|
||||||
|
val quantity = viewModel.getSneakerQuantity(sneakerId)
|
||||||
|
|
||||||
|
SneakerKorzinaButton(
|
||||||
|
sneakerShop = sneakerShop,
|
||||||
|
quantity = quantity,
|
||||||
|
onClick = { /* переход */ },
|
||||||
|
onIncrease = {
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, quantity + 1)
|
||||||
|
},
|
||||||
|
onDecrease = {
|
||||||
|
if (quantity > 1) {
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, quantity - 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRemove = { viewModel.removeSneakerFromCart(sneakerId) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,10 +38,6 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@ -205,9 +201,8 @@ fun SalesBar() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BottomNavigationBar() {
|
fun BottomNavigationBar(navController: NavController) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
@ -236,7 +231,7 @@ fun BottomNavigationBar() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
IconButton(onClick = { /* TODO: действие кнопки */ }) {
|
IconButton(onClick = { navController.navigate("favouriteSneakers_screen")}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.FavoriteBorder,
|
imageVector = Icons.Default.FavoriteBorder,
|
||||||
contentDescription = "favourite",
|
contentDescription = "favourite",
|
||||||
@ -245,7 +240,7 @@ fun BottomNavigationBar() {
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(20.dp))
|
Spacer(modifier = Modifier.width(20.dp))
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = { /* TODO: действие кнопки */ },
|
onClick = { navController.navigate("korzinaSneakers_screen") },
|
||||||
modifier = Modifier.offset(y = (-20).dp).size(80.dp)
|
modifier = Modifier.offset(y = (-20).dp).size(80.dp)
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
@ -321,12 +316,26 @@ fun SneakerSelection(sneakers: List<SneakerShop>, viewModel: MainViewModel) {
|
|||||||
SneakerButton(
|
SneakerButton(
|
||||||
sneakerShop = sneakerShop,
|
sneakerShop = sneakerShop,
|
||||||
isLiked = viewModel.isLiked(sneakerShop.sneaker.id),
|
isLiked = viewModel.isLiked(sneakerShop.sneaker.id),
|
||||||
|
isOrdered = viewModel.isOrdered(sneakerShop.sneaker.id),
|
||||||
onClick = { /* переход */ },
|
onClick = { /* переход */ },
|
||||||
// onFavoriteClick = { viewModel.toggleLike(sneakerShop.sneaker.id) }
|
|
||||||
onFavoriteClick = {
|
onFavoriteClick = {
|
||||||
viewModel.toggleLike(sneakerShop.sneaker.id)
|
viewModel.toggleLike(sneakerShop.sneaker.id)
|
||||||
val likedCount = viewModel.likedSneakers.values.count { it }
|
val likedCount = viewModel.likedSneakers.values.count { it }
|
||||||
Log.d("SneakerLike", "Лайкнуто кроссовок: $likedCount")
|
Log.d("SneakerLike", "Лайкнуто кроссовок: $likedCount")
|
||||||
|
},
|
||||||
|
onOrderClick = {
|
||||||
|
val sneakerId = sneakerShop.sneaker.id
|
||||||
|
|
||||||
|
if (!viewModel.isOrdered(sneakerId)) {
|
||||||
|
viewModel.toggleOrder(sneakerId)
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, 1)
|
||||||
|
} else {
|
||||||
|
viewModel.toggleOrder(sneakerId)
|
||||||
|
viewModel.setSneakerQuantity(sneakerId, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val orderCount = viewModel.orderedSneakers.values.count { it }
|
||||||
|
Log.d("SneakerOrder", "Добавлено в корзину кроссовок: $orderCount")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -337,11 +346,11 @@ fun SneakerSelection(sneakers: List<SneakerShop>, viewModel: MainViewModel) {
|
|||||||
fun SneakerButton(
|
fun SneakerButton(
|
||||||
sneakerShop: SneakerShop,
|
sneakerShop: SneakerShop,
|
||||||
isLiked: Boolean,
|
isLiked: Boolean,
|
||||||
|
isOrdered: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onFavoriteClick: () -> Unit
|
onFavoriteClick: () -> Unit,
|
||||||
|
onOrderClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
var isAddedToCart by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
Box(modifier = Modifier.padding(8.dp)) {
|
Box(modifier = Modifier.padding(8.dp)) {
|
||||||
Button(
|
Button(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
@ -376,17 +385,14 @@ fun SneakerButton(
|
|||||||
val icon = if (isLiked) Icons.Default.Favorite else Icons.Default.FavoriteBorder
|
val icon = if (isLiked) Icons.Default.Favorite else Icons.Default.FavoriteBorder
|
||||||
Icon(imageVector = icon, contentDescription = "Favourite", tint = Color.Red)
|
Icon(imageVector = icon, contentDescription = "Favourite", tint = Color.Red)
|
||||||
}
|
}
|
||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = {
|
onClick = onOrderClick,
|
||||||
isAddedToCart = !isAddedToCart
|
|
||||||
},
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.BottomEnd)
|
||||||
.size(32.dp)
|
.size(32.dp)
|
||||||
.padding(4.dp)
|
.padding(4.dp)
|
||||||
) {
|
) {
|
||||||
val iconRes = if (isAddedToCart) Icons.Default.ShoppingCart else Icons.Default.Add
|
val iconRes = if (isOrdered) Icons.Default.ShoppingCart else Icons.Default.Add
|
||||||
Icon(imageVector = iconRes, contentDescription = "Cart", tint = Color.Cyan)
|
Icon(imageVector = iconRes, contentDescription = "Cart", tint = Color.Cyan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ fun CategorySneakersContent(
|
|||||||
viewModel.sneakersCategories.sneakers.filter {
|
viewModel.sneakersCategories.sneakers.filter {
|
||||||
viewModel.selectedCategory == null || it.categoryId == viewModel.selectedCategory?.id
|
viewModel.selectedCategory == null || it.categoryId == viewModel.selectedCategory?.id
|
||||||
}.map { sneaker ->
|
}.map { sneaker ->
|
||||||
SneakerShop(sneaker, false)
|
SneakerShop(sneaker, false, false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
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.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.testktor.ViewModel.MainViewModel
|
||||||
|
import com.example.testktor.method.main.SneakerCategorySelection
|
||||||
|
import com.example.testktor.method.main.TopWriteNavigationBar
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FavouriteSneakersScreen(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFFF7F7F9))
|
||||||
|
) {
|
||||||
|
FavouriteSneakersContent(navController, viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FavouriteSneakersContent(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
val likedSneakers = remember(viewModel.selectedCategory, viewModel.likedSneakers) {
|
||||||
|
viewModel.getLikedSneakersByCategory()
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
TopWriteNavigationBar(navController, "Избранное", viewModel)
|
||||||
|
|
||||||
|
SneakerCategorySelection(likedSneakers, viewModel)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
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.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.testktor.ViewModel.MainViewModel
|
||||||
|
import com.example.testktor.method.main.BottomKorzinaNavigationBar
|
||||||
|
import com.example.testktor.method.main.SneakerKorzinaSelection
|
||||||
|
import com.example.testktor.method.main.TopWriteNavigationBar
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun KorzinaSneakersScreen(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFFF7F7F9))
|
||||||
|
) {
|
||||||
|
KorzinaSneakersContent(navController, viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun KorzinaSneakersContent(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
val orderedSneakers by remember(viewModel.orderedSneakers, viewModel.selectedCategory) {
|
||||||
|
derivedStateOf { viewModel.getOrderedSneakersByCategory() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
TopWriteNavigationBar(navController, "Корзина", viewModel)
|
||||||
|
|
||||||
|
SneakerKorzinaSelection(sneakers = orderedSneakers, viewModel = viewModel)
|
||||||
|
|
||||||
|
BottomKorzinaNavigationBar(navController, orderedSneakers, viewModel)
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,7 @@ fun SneakersContent(
|
|||||||
var sneakers by remember(viewModel.sneakersCategories) {
|
var sneakers by remember(viewModel.sneakersCategories) {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
viewModel.sneakersCategories.sneakers.map { sneaker ->
|
viewModel.sneakersCategories.sneakers.map { sneaker ->
|
||||||
SneakerShop(sneaker, false)
|
SneakerShop(sneaker, false, false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -84,6 +84,6 @@ fun SneakersContent(
|
|||||||
OverSmth("Популярное", navController)
|
OverSmth("Популярное", navController)
|
||||||
SneakerSelection(sneakers = sneakers, viewModel)
|
SneakerSelection(sneakers = sneakers, viewModel)
|
||||||
SalesBar()
|
SalesBar()
|
||||||
BottomNavigationBar()
|
BottomNavigationBar(navController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,19 +27,19 @@ fun PopularSneakersScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(Color(0xFFF7F7F9))
|
.background(Color(0xFFF7F7F9))
|
||||||
) {
|
) {
|
||||||
FavouriteSneakersContent(navController, viewModel)
|
PopularSneakersContent(navController, viewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun FavouriteSneakersContent(
|
fun PopularSneakersContent(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
var sneakers by remember(viewModel.sneakersCategories) {
|
var sneakers by remember(viewModel.sneakersCategories) {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
viewModel.sneakersCategories.sneakers.map { sneaker ->
|
viewModel.sneakersCategories.sneakers.map { sneaker ->
|
||||||
SneakerShop(sneaker, false)
|
SneakerShop(sneaker, false, false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
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.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import com.example.testktor.ViewModel.MainViewModel
|
||||||
|
import com.example.testktor.method.main.TopWriteNavigationBar
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SuccessOrderSneakersScreen(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(Color(0xFFF7F7F9))
|
||||||
|
) {
|
||||||
|
SuccessOrderSneakersContent(navController, viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SuccessOrderSneakersContent(
|
||||||
|
navController: NavController,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
){
|
||||||
|
Column {
|
||||||
|
TopWriteNavigationBar(navController, "Success order", viewModel)
|
||||||
|
|
||||||
|
Text(text = "Заказ оформлен", fontSize = 30.sp)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user