Feature: order and basket completed

This commit is contained in:
Emelyanov535 2023-12-10 14:24:10 +04:00
parent 5c105ebdb2
commit 37c45d0cf7
17 changed files with 313 additions and 93 deletions

View File

@ -1,9 +1,12 @@
package com.example.android_programming.api
import com.example.android_programming.api.model.BasketSneakerRemote
import com.example.android_programming.api.model.OrderRemote
import com.example.android_programming.api.model.OrderSneakerRemote
import com.example.android_programming.api.model.SneakerRemote
import com.example.android_programming.api.model.UserRemote
import com.example.android_programming.api.model.UserRemoteSignIn
import com.example.android_programming.model.Order
import com.example.android_programming.model.Sneaker
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
@ -106,6 +109,42 @@ interface BackendService {
@Path("sneakerId") sneakerId: Int,
)
@GET("basket/getUserPrice/{userId}")
suspend fun getTotalPriceForUserBasket(
@Path("userId") userId: Int
): Double
@GET("basket/deleteAllSneakerFromBasket/{basketId}")
suspend fun deleteAllSneakerFromBasket(
@Path("basketId") basketId: Int
)
//ORDER
@POST("order/createOrderSneaker")
suspend fun createOrderSneaker(
@Body orderSneaker: OrderSneakerRemote
)
@POST("order/create")
suspend fun createOrder(
@Body order: OrderRemote
): Long
@GET("order/getUserOrders/{userId}")
suspend fun getUserOrders(
@Path("userId") userId: Int
) : List<OrderRemote>
@GET("order/getSneakerFromOrder/{orderId}")
suspend fun getSneakerFromOrder(
@Path("orderId") orderId: Int
) : List<SneakerRemote>
@GET("order/deleteOrder/{orderId}")
suspend fun deleteOrder(
@Path("orderId") orderId: Int
)
companion object {
private const val BASE_URL = "https://59k4pfj3-8080.euw.devtunnels.ms/api/"

View File

@ -0,0 +1,44 @@
package com.example.android_programming.api.model
import androidx.room.ColumnInfo
import androidx.room.PrimaryKey
import com.example.android_programming.model.Order
import com.example.android_programming.model.Sneaker
import kotlinx.serialization.Serializable
@Serializable
data class OrderRemote(
val id: Int? = 0,
val date: Long = 0L,
val city: String = "",
val street: String = "",
val house: String = "",
val subtotal: Double = 0.0,
val taxes: Double = 0.0,
val total: Double = 0.0,
val userId: Int = 0
)
fun OrderRemote.toOrder(): Order = Order(
id,
date,
city,
street,
house,
subtotal,
taxes,
total,
userId
)
fun Order.toOrderRemote():OrderRemote = OrderRemote(
orderId,
date,
city,
street,
house,
subtotal,
taxes,
total,
creatorUserId
)

View File

@ -0,0 +1,24 @@
package com.example.android_programming.api.model
import com.example.android_programming.model.BasketSneakers
import com.example.android_programming.model.OrderSneaker
import kotlinx.serialization.Serializable
@Serializable
data class OrderSneakerRemote (
val orderId: Int = 0,
val sneakerId: Int = 0,
val quantity: Int = 0
)
fun OrderSneakerRemote.toOrderSneaker(): OrderSneaker = OrderSneaker(
orderId,
sneakerId,
quantity
)
fun OrderSneaker.toOrderSneakerRemote():OrderSneakerRemote = OrderSneakerRemote(
orderId,
sneakerId,
quantity
)

View File

@ -69,8 +69,12 @@ class RestBasketRepository(
override suspend fun existSneaker(basketId: Int, sneakerId: Int): Boolean {
return service.getSneaker(basketId, sneakerId)
}
//
// override suspend fun getTotalPriceForUser(userId: Int): Double? {
// TODO("Not yet implemented")
// }
override suspend fun getTotalPriceForUser(userId: Int): Double? {
return service.getTotalPriceForUserBasket(userId)
}
override suspend fun deleteAllSneakerFromBasket(basketId: Int) {
service.deleteAllSneakerFromBasket(basketId)
}
}

View File

@ -0,0 +1,39 @@
package com.example.android_programming.api.repository
import com.example.android_programming.api.BackendService
import com.example.android_programming.api.model.toOrder
import com.example.android_programming.api.model.toOrderRemote
import com.example.android_programming.api.model.toOrderSneakerRemote
import com.example.android_programming.api.model.toSneaker
import com.example.android_programming.businessLogic.repo.OrderRepository
import com.example.android_programming.model.Order
import com.example.android_programming.model.OrderSneaker
import com.example.android_programming.model.Sneaker
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
class RestOrderRepository(private val service: BackendService): OrderRepository {
override suspend fun createOrder(order: Order): Long {
return service.createOrder(order.toOrderRemote())
}
override suspend fun insertOrderSneaker(orderSneaker: OrderSneaker) {
service.createOrderSneaker(orderSneaker.toOrderSneakerRemote())
}
override suspend fun delete(orderId: Int) {
service.deleteOrder(orderId)
}
override suspend fun getSneakerFromOrder(id: Int): Flow<List<Sneaker>> {
val sneakersRemoteList = service.getSneakerFromOrder(id)
val sneakersList = sneakersRemoteList.map { it.toSneaker() }
return flowOf(sneakersList.toList())
}
override suspend fun getUserOrders(id: Int): Flow<List<Order>> {
val ordersRemoteList = service.getUserOrders(id)
val ordersList = ordersRemoteList.map { it.toOrder() }
return flowOf(ordersList.toList())
}
}

View File

@ -22,5 +22,6 @@ interface BasketRepository {
suspend fun decrementSneakerQuantity(basketId: Int, sneakerId: Int)
suspend fun getQuantity(basketId: Int, sneakerId: Int): Int?
suspend fun existSneaker(basketId: Int, sneakerId: Int): Boolean
// suspend fun getTotalPriceForUser(userId: Int): Double?
suspend fun getTotalPriceForUser(userId: Int): Double?
suspend fun deleteAllSneakerFromBasket(basketId: Int)
}

View File

@ -3,14 +3,15 @@ package com.example.android_programming.businessLogic.repo
import com.example.android_programming.model.Order
import com.example.android_programming.model.OrderSneaker
import com.example.android_programming.model.OrderWithSneakers
import com.example.android_programming.model.Sneaker
import com.example.android_programming.model.UserWithOrder
import kotlinx.coroutines.flow.Flow
interface OrderRepository {
suspend fun createOrder(order: Order): Long
suspend fun insertOrderSneaker(orderSneaker: OrderSneaker)
suspend fun delete(order: Order)
fun getOrderWithSneakers(id: Int): Flow<OrderWithSneakers>
fun getAllOrder(): Flow<List<Order>>
fun getUserOrders(id: Int) : Flow<UserWithOrder>
suspend fun delete(orderId: Int)
suspend fun getSneakerFromOrder(id: Int): Flow<List<Sneaker>>
// fun getAllOrder(): Flow<List<Order>>
suspend fun getUserOrders(id: Int) : Flow<List<Order>>
}

View File

@ -89,4 +89,7 @@ class BasketViewModel(private val basketRepository: BasketRepository): ViewModel
}
}
}
fun deleteAllSneakerFromBasket(basketId: Int) = viewModelScope.launch {
basketRepository.deleteAllSneakerFromBasket(basketId)
}
}

View File

@ -32,53 +32,54 @@ class OrderViewModel(private val orderRepository: OrderRepository, private val b
_selectedItems.value = items
}
fun deleteOrder(order: Order) = viewModelScope.launch {
orderRepository.delete(order)
fun deleteOrder(orderId: Int) = viewModelScope.launch {
orderRepository.delete(orderId)
}
fun getOrderList(id: Int) : Flow<UserWithOrder> {
suspend fun getOrderList(id: Int) : Flow<List<Order>> {
return orderRepository.getUserOrders(id)
}
fun getOrderWithSneakers(id: Int) : Flow<OrderWithSneakers> {
return orderRepository.getOrderWithSneakers(id)
suspend fun getOrderWithSneakers(id: Int) : Flow<List<Sneaker>> {
return orderRepository.getSneakerFromOrder(id)
}
// fun createOrder() = viewModelScope.launch {
// val userId = GlobalUser.getInstance().getUser()?.userId!!
// val order = Order(
// date = Date().time,
// city = city.value,
// street = street.value,
// house = house.value,
// subtotal = getSubTotal(userId),
// taxes = "%.2f".format(getSubTotal(userId) * 0.05).toDouble(),
// total = "%.2f".format(getSubTotal(userId) * 0.05 + getSubTotal(userId)).toDouble(),
// creatorUserId = GlobalUser.getInstance().getUser()?.userId!!
// )
//
// val orderId = orderRepository.createOrder(order)
//
//// for (sneaker in selectedItems.value.orEmpty()) {
//// val userId = GlobalUser.getInstance().getUser()?.userId!!
//// val orderSneaker = basketRepository.getQuantity(userId, sneaker.sneakerId!!)
//// ?.let { OrderSneaker( orderId.toInt(), sneaker.sneakerId!!, it) }
//// if (orderSneaker != null) {
//// orderRepository.insertOrderSneaker(orderSneaker)
//// }
//// }
// city.value = ""
// street.value = ""
// house.value = ""
// }
fun createOrder() = viewModelScope.launch {
val userId = GlobalUser.getInstance().getUser()?.userId!!
val subTotal = getSubTotal(userId)
val order = Order(
date = Date().time,
city = city.value,
street = street.value,
house = house.value,
subtotal = subTotal,
taxes = "%.2f".format(subTotal * 0.05).toDouble(),
total = "%.2f".format(subTotal * 0.05 + subTotal).toDouble(),
creatorUserId = GlobalUser.getInstance().getUser()?.userId!!
)
// fun updateSubTotal(userId: Int) {
// viewModelScope.launch {
// _subTotal.value = getSubTotal(userId)
// }
// }
val orderId = orderRepository.createOrder(order)
// suspend fun getSubTotal(userId: Int): Double {
// return basketRepository.getTotalPriceForUser(userId) ?: 0.0
// }
for (sneaker in selectedItems.value.orEmpty()) {
val userId = GlobalUser.getInstance().getUser()?.userId!!
val orderSneaker = basketRepository.getQuantity(userId, sneaker.sneakerId!!)
?.let { OrderSneaker( orderId.toInt(), sneaker.sneakerId!!, it) }
if (orderSneaker != null) {
orderRepository.insertOrderSneaker(orderSneaker)
}
}
city.value = ""
street.value = ""
house.value = ""
}
fun updateSubTotal(userId: Int) {
viewModelScope.launch {
_subTotal.value = getSubTotal(userId)
}
}
suspend fun getSubTotal(userId: Int): Double {
return basketRepository.getTotalPriceForUser(userId) ?: 0.0
}
}

View File

@ -0,0 +1,34 @@
package com.example.android_programming.composeui.Screens
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Snackbar
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun ErrorSnackbar(
) {
Text(text = "случилось говно")
}

View File

@ -10,7 +10,12 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
@ -22,12 +27,17 @@ import com.example.android_programming.businessLogic.vmodel.AppViewModelProvider
import com.example.android_programming.businessLogic.vmodel.OrderViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
@Composable
fun MyOrderScreen(orderViewModel: OrderViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
val userId = GlobalUser.getInstance().getUser()?.userId
val userWithOrder = orderViewModel.getOrderList(userId!!).collectAsState(null).value?.orders
var usersOrder by remember { mutableStateOf<List<Order>>(emptyList()) }
LaunchedEffect(userId) {
usersOrder = orderViewModel.getOrderList(userId!!).first()
}
Column(
modifier = Modifier
@ -49,8 +59,8 @@ fun MyOrderScreen(orderViewModel: OrderViewModel = viewModel(factory = AppViewMo
modifier = Modifier
.fillMaxSize()
) {
if (userWithOrder != null) {
for (item in userWithOrder) {
if (usersOrder != null) {
for (item in usersOrder) {
OrderCard(item)
}
}

View File

@ -20,8 +20,12 @@ import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowLeft
import androidx.compose.material.icons.filled.KeyboardArrowRight
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
@ -36,16 +40,15 @@ import com.example.android_programming.model.Order
import com.example.android_programming.model.Sneaker
import com.example.android_programming.businessLogic.vmodel.AppViewModelProvider
import com.example.android_programming.businessLogic.vmodel.OrderViewModel
import kotlinx.coroutines.flow.first
import java.util.Date
@Composable
fun OrderCard(order: Order, orderViewModel: OrderViewModel = viewModel(factory = AppViewModelProvider.Factory)){
val SneakerList = order?.orderId?.let {
orderViewModel.getOrderWithSneakers(it)
var sneakers by remember { mutableStateOf<List<Sneaker>>(emptyList()) }
LaunchedEffect(order.orderId) {
sneakers = orderViewModel.getOrderWithSneakers(order.orderId!!).first()
}
val sneakerWithOrder by SneakerList!!.collectAsState(null)
val sneakerList: List<Sneaker>? = sneakerWithOrder?.sneakers
Row(
modifier = Modifier
.fillMaxWidth()
@ -62,8 +65,8 @@ fun OrderCard(order: Order, orderViewModel: OrderViewModel = viewModel(factory =
Text("${order.orderId}")
Text("${Date(order.date)}")
Row(){
if (sneakerList != null) {
for(sneaker in sneakerList){
if (sneakers != null) {
for(sneaker in sneakers){
Image(
contentScale = ContentScale.FillBounds,
painter = painterResource(id = sneaker.photo),
@ -81,7 +84,7 @@ fun OrderCard(order: Order, orderViewModel: OrderViewModel = viewModel(factory =
contentColor = Color.White
),
onClick = {
orderViewModel.deleteOrder(order)
orderViewModel.deleteOrder(order.orderId!!)
},
modifier = Modifier
.fillMaxWidth()

View File

@ -27,6 +27,10 @@ import com.example.android_programming.model.Sneaker
import com.example.android_programming.businessLogic.vmodel.AppViewModelProvider
import com.example.android_programming.businessLogic.vmodel.BasketViewModel
import com.example.android_programming.businessLogic.vmodel.OrderViewModel
import com.example.android_programming.model.BasketSneakers
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@Composable
@ -55,12 +59,16 @@ fun OrderScreen(navHostController: NavHostController, basketViewModel: BasketVie
contentColor = Color.White
),
onClick = {
// if(GlobalUser.getInstance().getUser() != null){
// orderViewModel.createOrder()
// navHostController.navigate("home")
// }else{
// navHostController.navigate("login")
// }
if(GlobalUser.getInstance().getUser() != null){
orderViewModel.createOrder()
runBlocking {
launch(Dispatchers.Default) {
basketViewModel.deleteAllSneakerFromBasket(basketViewModel.getUserBasketId(userId!!)) }
}
navHostController.navigate("home")
}else{
navHostController.navigate("login")
}
},
modifier = Modifier
.fillMaxWidth()

View File

@ -22,7 +22,7 @@ import com.example.android_programming.businessLogic.vmodel.OrderViewModel
@Composable
fun SubTotal(orderViewModel: OrderViewModel) {
val userId = GlobalUser.getInstance().getUser()?.userId!!
// orderViewModel.updateSubTotal(userId)
orderViewModel.updateSubTotal(userId)
val subTotal = orderViewModel.subTotal.value
Column(
modifier = Modifier

View File

@ -43,6 +43,7 @@ import com.example.android_programming.model.Basket
import com.example.android_programming.businessLogic.vmodel.AppViewModelProvider
import com.example.android_programming.businessLogic.vmodel.BasketViewModel
import com.example.android_programming.businessLogic.vmodel.UserViewModel
import com.example.android_programming.composeui.Screens.ErrorSnackbar
@Composable
fun SignInCard(navController: NavHostController, userViewModel: UserViewModel = viewModel(factory = AppViewModelProvider.Factory), basketViewModel: BasketViewModel = viewModel(factory = AppViewModelProvider.Factory)) {

View File

@ -1,24 +1,32 @@
package com.example.android_programming.database.repository
import com.example.android_programming.businessLogic.repo.OrderRepository
import com.example.android_programming.database.dao.OrderDao
import com.example.android_programming.model.Order
import com.example.android_programming.model.OrderSneaker
import com.example.android_programming.model.OrderWithSneakers
import com.example.android_programming.model.UserWithOrder
import kotlinx.coroutines.flow.Flow
class OrderRepoImpl(private val orderDao: OrderDao) : OrderRepository {
override suspend fun createOrder(order: Order): Long = orderDao.createOrder(order)
override suspend fun insertOrderSneaker(orderSneaker: OrderSneaker) = orderDao.insertOrderSneaker(orderSneaker)
override suspend fun delete(order: Order) = orderDao.delete(order)
override fun getOrderWithSneakers(id: Int): Flow<OrderWithSneakers> = orderDao.getOrderWithSneakers(id)
override fun getAllOrder(): Flow<List<Order>> = orderDao.getAllOrder()
override fun getUserOrders(id: Int): Flow<UserWithOrder> = orderDao.getUserOrders(id)
}
//package com.example.android_programming.database.repository
//
//import com.example.android_programming.businessLogic.repo.OrderRepository
//import com.example.android_programming.database.dao.OrderDao
//import com.example.android_programming.model.Order
//import com.example.android_programming.model.OrderSneaker
//import com.example.android_programming.model.OrderWithSneakers
//import com.example.android_programming.model.Sneaker
//import com.example.android_programming.model.UserWithOrder
//import kotlinx.coroutines.flow.Flow
//
//class OrderRepoImpl(private val orderDao: OrderDao) : OrderRepository {
//
// override suspend fun createOrder(order: Order): Long = orderDao.createOrder(order)
//
// override suspend fun insertOrderSneaker(orderSneaker: OrderSneaker) = orderDao.insertOrderSneaker(orderSneaker)
// override suspend fun getSneakerFromOrder(id: Int): Flow<List<Sneaker>> {
// TODO("Not yet implemented")
// }
//
// override suspend fun getUserOrders(id: Int): Flow<List<Order>> {
// TODO("Not yet implemented")
// }
//
//// override suspend fun delete(order: Order) = orderDao.delete(order)
////
//// override fun getOrderWithSneakers(id: Int): Flow<OrderWithSneakers> = orderDao.getOrderWithSneakers(id)
////
//// override fun getAllOrder(): Flow<List<Order>> = orderDao.getAllOrder()
////
//// override fun getUserOrders(id: Int): Flow<UserWithOrder> = orderDao.getUserOrders(id)
//}

View File

@ -3,12 +3,12 @@ package com.example.android_programming.di
import android.content.Context
import com.example.android_programming.api.BackendService
import com.example.android_programming.api.repository.RestBasketRepository
import com.example.android_programming.api.repository.RestOrderRepository
import com.example.android_programming.api.repository.RestSneakerRepository
import com.example.android_programming.api.repository.RestUserRepository
import com.example.android_programming.database.AppDatabase
import com.example.android_programming.database.repository.RemoteKeysRepositoryImpl
import com.example.android_programming.businessLogic.repo.BasketRepository
import com.example.android_programming.database.repository.OrderRepoImpl
import com.example.android_programming.businessLogic.repo.OrderRepository
import com.example.android_programming.businessLogic.repo.SneakerRepository
import com.example.android_programming.businessLogic.repo.UserRepository
@ -31,7 +31,7 @@ class AppDataContainer(private val context: Context) : AppContainer {
}
override val orderRepo: OrderRepository by lazy {
OrderRepoImpl(AppDatabase.getInstance(context).orderDao())
RestOrderRepository(BackendService.getInstance())
}
private val sneakerRepository: SneakerRepoImpl by lazy {
SneakerRepoImpl(AppDatabase.getInstance(context).sneakerDao())