Криво-косо готов экран корзины

This commit is contained in:
Данила Мочалов 2023-12-22 04:41:27 +04:00
parent 247fe61d9e
commit caaebc7587
12 changed files with 228 additions and 67 deletions

View File

@ -64,7 +64,7 @@ object AppModule {
@Provides @Provides
@Singleton @Singleton
fun provideOrderRepository(db: AppDatabase, restOrderRepository: RestOrderRepository) : OrderRepository { fun provideOrderRepository(db: AppDatabase, restOrderRepository: RestOrderRepository) : OrderRepository {
return OrderRepository(db.orderDao(), db.productDao(), db.orderProductDao(), restOrderRepository) return OrderRepository(db, db.orderDao(), db.productDao(), db.orderProductDao(), restOrderRepository)
} }
@Provides @Provides

View File

@ -1,5 +1,6 @@
package com.example.shawarma.data.api package com.example.shawarma.data.api
import com.example.shawarma.data.api.models.OrderListResponse
import com.example.shawarma.data.api.models.OrderModelRemote import com.example.shawarma.data.api.models.OrderModelRemote
import com.example.shawarma.data.api.models.OrderProductRemote import com.example.shawarma.data.api.models.OrderProductRemote
import com.example.shawarma.data.api.models.ProductListResponse import com.example.shawarma.data.api.models.ProductListResponse
@ -77,9 +78,15 @@ interface MyServerService {
@GET("order/unpaid") @GET("order/unpaid")
suspend fun getUnpaidOrder(@Header("Authorization") token: String) : OrderModelRemote suspend fun getUnpaidOrder(@Header("Authorization") token: String) : OrderModelRemote
@GET("order/paid/{after}")
suspend fun getPaidOrdersList(@Path("after") after: Int, @Header("Authorization") token: String) : OrderListResponse
@POST("order") @POST("order")
suspend fun insertOrder(@Body order: OrderModelRemote, @Header("Authorization") token: String) : OrderModelRemote? suspend fun insertOrder(@Body order: OrderModelRemote, @Header("Authorization") token: String) : OrderModelRemote?
@PUT("order")
suspend fun updateOrder(@Body order: OrderModelRemote, @Header("Authorization") token: String) : OrderModelRemote?
// //
// ORDER PRODUCTS // ORDER PRODUCTS
// //
@ -90,6 +97,9 @@ interface MyServerService {
@PUT("order/product") @PUT("order/product")
suspend fun updateOrderProduct(@Body orderProduct: OrderProductRemote, @Header("Authorization") token: String) suspend fun updateOrderProduct(@Body orderProduct: OrderProductRemote, @Header("Authorization") token: String)
@POST("order/product/delete")
suspend fun deleteOrderProduct(@Body orderProduct: OrderProductRemote, @Header("Authorization") token: String)
companion object { companion object {
private const val BASE_URL = "https://10.0.2.2:80/api/" private const val BASE_URL = "https://10.0.2.2:80/api/"

View File

@ -0,0 +1,78 @@
package com.example.shawarma.data.api.mediators
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.example.shawarma.data.api.MyServerService
import com.example.shawarma.data.api.models.OrderListResponse
import com.example.shawarma.data.api.models.toOrderModel
import com.example.shawarma.data.db.AppDatabase
import com.example.shawarma.data.models.OrderModel
import com.example.shawarma.data.models.OrderWithProducts
import java.io.IOException
@OptIn(ExperimentalPagingApi::class)
class OrderRemoteMediator (
private val database: AppDatabase,
private val serverService: MyServerService,
private val query: String,
private val token: String
) : RemoteMediator<Int, OrderWithProducts>(){
private val orderDao = database.orderDao()
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, OrderWithProducts>
): MediatorResult {
return try {
var loadKey = when (loadType) {
LoadType.REFRESH -> null
LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastItem = state.lastItemOrNull()
?: return MediatorResult.Success(endOfPaginationReached = true)
lastItem.order.id
}
}
if (loadKey == null) {
loadKey = 0
}
val response: OrderListResponse = when (query) {
"paid" -> {
serverService.getPaidOrdersList(after = loadKey, token = token)
}
// "ready" -> {
// serverService.getDiscountsList(after = loadKey, token = token)
// }
// "served" -> {
// serverService.getItemsList(after = loadKey, token = token)
// }
else -> {
OrderListResponse()
}
}
database.withTransaction {
if (loadType == LoadType.REFRESH) {
orderDao.deleteByQuery(query)
}
val orders = mutableListOf<OrderModel>()
for (order in response.orders) {
orders.add(order.toOrderModel())
}
orderDao.insertAll(orders)
}
MediatorResult.Success(endOfPaginationReached = response.nextKey == -1)
} catch (e: IOException) {
MediatorResult.Error(e)
}
}
}

View File

@ -13,6 +13,12 @@ data class OrderModelRemote(
val order_products: List<OrderProductRemote> = listOf() val order_products: List<OrderProductRemote> = listOf()
) )
@Serializable
data class OrderListResponse(
val orders: List<OrderModelRemote> = listOf(),
val nextKey: Int? = null
)
fun OrderModelRemote.toOrderModel() : OrderModel = OrderModel( fun OrderModelRemote.toOrderModel() : OrderModel = OrderModel(
id, status, user_id, date = date id, status, user_id, date = date
) )

View File

@ -14,4 +14,8 @@ class RestOrderProductRepository @Inject constructor(
suspend fun updateOrderProduct(token: String, orderProduct: OrderProductRemote) { suspend fun updateOrderProduct(token: String, orderProduct: OrderProductRemote) {
service.updateOrderProduct(orderProduct, token) service.updateOrderProduct(orderProduct, token)
} }
suspend fun deleteOrderProduct(token: String, orderProduct: OrderProductRemote) {
service.deleteOrderProduct(orderProduct, token)
}
} }

View File

@ -14,4 +14,8 @@ class RestOrderRepository@Inject constructor(
suspend fun insertOrder(token: String, order: OrderModelRemote): OrderModelRemote? { suspend fun insertOrder(token: String, order: OrderModelRemote): OrderModelRemote? {
return service.insertOrder(order, token) return service.insertOrder(order, token)
} }
suspend fun updateOrder(token: String, order: OrderModelRemote): OrderModelRemote? {
return service.updateOrder(order, token)
}
} }

View File

@ -1,5 +1,6 @@
package com.example.shawarma.data.interfaces.dao package com.example.shawarma.data.interfaces.dao
import androidx.paging.PagingSource
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Delete import androidx.room.Delete
import androidx.room.Insert import androidx.room.Insert
@ -19,11 +20,40 @@ interface OrderDao {
@Query("select * from orders") @Query("select * from orders")
fun getAll(): Flow<List<OrderWithProducts>> fun getAll(): Flow<List<OrderWithProducts>>
@Query("select * from orders where orders.id =:id") @Query("select * from orders where orders.id =:id")
fun getById(id: Int): Flow<List<OrderWithProducts>> fun getById(id: Int): Flow<OrderWithProducts>
@Query("select * from orders where orders.user_id =:userId") @Query("select * from orders where orders.user_id =:userId")
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> fun getByUserId(userId: Int): Flow<List<OrderWithProducts>>
@Query("select * from orders where orders.user_id =:userId and orders.order_status = 'Неоплачено'") @Query("select * from orders where orders.user_id =:userId and orders.order_status = 'Неоплачено'")
fun getUnpaidByUser(userId: Int) : Flow<OrderWithProducts> fun getUnpaidByUser(userId: Int) : Flow<OrderWithProducts>
@Query("select * from orders where orders.user_id =:userId and (orders.order_status = 'Готовится' or orders.order_status = 'Готово')") @Query("select * from orders where orders.user_id =:userId and (orders.order_status = 'Готовится' or orders.order_status = 'Готово')")
fun getPaidByUser(userId: Int) : Flow<List<OrderWithProducts>> fun getPaidByUser(userId: Int) : Flow<List<OrderWithProducts>>
suspend fun insertAll(orders: List<OrderModel>) {
for (order in orders) {
insert(order)
}
}
@Query("select * from orders where orders.order_status != 'Неоплачено'")
fun getPaidPaged(): PagingSource<Int, OrderWithProducts>
@Query("delete from orders where orders.order_status = 'Готовится'")
fun deleteAllPaid()
@Query("delete from orders where orders.order_status = 'Готово'")
fun deleteAllReady()
@Query("delete from orders where orders.order_status = 'Выдано'")
fun deleteAllServed()
fun deleteByQuery(query: String) {
if (query == "paid") {
deleteAllPaid()
}
if (query == "ready") {
deleteAllReady()
}
if (query == "served") {
deleteAllServed()
}
}
} }

View File

@ -18,8 +18,9 @@ class OrderProductRepository @Inject constructor(
orderProductDao.update(orderProduct) orderProductDao.update(orderProduct)
return restOrderProductRepository.updateOrderProduct(token, orderProduct.toOrderProductRemote()) return restOrderProductRepository.updateOrderProduct(token, orderProduct.toOrderProductRemote())
} }
suspend fun delete(order: OrderProductModel) { suspend fun delete(token: String, orderProduct: OrderProductModel) {
return orderProductDao.delete(order) orderProductDao.delete(orderProduct)
restOrderProductRepository.deleteOrderProduct(token, orderProduct.toOrderProductRemote())
} }
} }

View File

@ -1,10 +1,16 @@
package com.example.shawarma.data.repos package com.example.shawarma.data.repos
import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.example.shawarma.data.api.MyServerService
import com.example.shawarma.data.api.mediators.OrderRemoteMediator
import com.example.shawarma.data.api.models.toOrderModel import com.example.shawarma.data.api.models.toOrderModel
import com.example.shawarma.data.api.models.toOrderModelRemote import com.example.shawarma.data.api.models.toOrderModelRemote
import com.example.shawarma.data.api.models.toOrderProductModel import com.example.shawarma.data.api.models.toOrderProductModel
import com.example.shawarma.data.api.models.toProductModel
import com.example.shawarma.data.api.repos.RestOrderRepository import com.example.shawarma.data.api.repos.RestOrderRepository
import com.example.shawarma.data.db.AppDatabase
import com.example.shawarma.data.interfaces.dao.OrderDao import com.example.shawarma.data.interfaces.dao.OrderDao
import com.example.shawarma.data.interfaces.dao.OrderProductDao import com.example.shawarma.data.interfaces.dao.OrderProductDao
import com.example.shawarma.data.interfaces.dao.ProductDao import com.example.shawarma.data.interfaces.dao.ProductDao
@ -15,20 +21,23 @@ import kotlinx.coroutines.flow.first
import javax.inject.Inject import javax.inject.Inject
class OrderRepository @Inject constructor( class OrderRepository @Inject constructor(
private val database: AppDatabase,
private val orderDao: OrderDao, private val orderDao: OrderDao,
private val productDao: ProductDao, private val productDao: ProductDao,
private val orderProductDao: OrderProductDao, private val orderProductDao: OrderProductDao,
private val restRepository: RestOrderRepository private val restRepository: RestOrderRepository
){ ){
suspend fun insert(token: String, order: OrderModel): OrderModel? { suspend fun insert(token: String, order: OrderModel): OrderModel? {
orderDao.insert(order)
val result = restRepository.insertOrder(token, order.toOrderModelRemote()) val result = restRepository.insertOrder(token, order.toOrderModelRemote())
if (result == null) { if (result == null) {
return result return result
} }
return result.toOrderModel() return result.toOrderModel()
} }
suspend fun update(order:OrderModel) { suspend fun update(token: String, order:OrderModel) {
return orderDao.update(order) orderDao.update(order)
restRepository.updateOrder(token, order.toOrderModelRemote())
} }
suspend fun delete(order: OrderModel) { suspend fun delete(order: OrderModel) {
return orderDao.delete(order) return orderDao.delete(order)
@ -36,7 +45,7 @@ class OrderRepository @Inject constructor(
fun getAll(): Flow<List<OrderWithProducts>> { fun getAll(): Flow<List<OrderWithProducts>> {
return orderDao.getAll() return orderDao.getAll()
} }
fun getById(id: Int): Flow<List<OrderWithProducts>> { fun getById(id: Int): Flow<OrderWithProducts>{
return orderDao.getById(id) return orderDao.getById(id)
} }
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> { fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> {
@ -44,14 +53,16 @@ class OrderRepository @Inject constructor(
} }
suspend fun getUnpaidByUser(token: String) : OrderWithProducts? { suspend fun getUnpaidByUser(token: String) : OrderWithProducts? {
val order = restRepository.getUnpaidOrder(token) val order = restRepository.getUnpaidOrder(token)
if (orderDao.getUnpaidByUser(order.user_id!!).first() != null) { if (order!!.id == null) {
return orderDao.getUnpaidByUser(order.user_id!!).first() return null
}
if (orderDao.getById(order.id!!).first() != null) {
orderDao.delete(order.toOrderModel())
} }
if (order!!.id != null) { if (order!!.id != null) {
orderDao.insert(order.toOrderModel()) orderDao.insert(order.toOrderModel())
for (product in order.order_products) { for (product in order.order_products) {
orderProductDao.insert(product.toOrderProductModel()) orderProductDao.insert(product.toOrderProductModel())
productDao.insert(product.product!!.toProductModel())
} }
return orderDao.getUnpaidByUser(order.user_id!!).first() return orderDao.getUnpaidByUser(order.user_id!!).first()
} }
@ -60,4 +71,15 @@ class OrderRepository @Inject constructor(
fun getPaidByUser(userId: Int) : Flow<List<OrderWithProducts>> { fun getPaidByUser(userId: Int) : Flow<List<OrderWithProducts>> {
return orderDao.getPaidByUser(userId) return orderDao.getPaidByUser(userId)
} }
@OptIn(ExperimentalPagingApi::class)
fun getPaidPaged(token: String): Flow<PagingData<OrderWithProducts>> = Pager(
config = PagingConfig(
pageSize = 6,
enablePlaceholders = false
),
pagingSourceFactory = orderDao::getPaidPaged,
remoteMediator = OrderRemoteMediator(database = database, serverService = MyServerService.getInstance(), query = "paid", token = token)
).flow
} }

View File

@ -36,6 +36,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex import androidx.compose.ui.zIndex
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.shawarma.data.models.OrderWithProducts import com.example.shawarma.data.models.OrderWithProducts
import com.example.shawarma.data.sharedpref.PreferencesManager import com.example.shawarma.data.sharedpref.PreferencesManager
import com.example.shawarma.ui.theme.MarckFamily import com.example.shawarma.ui.theme.MarckFamily
@ -59,12 +60,13 @@ fun CartScreen() {
@Composable @Composable
fun CartWidget(){ fun CartWidget(){
val preferencesManager = PreferencesManager(LocalContext.current) val preferencesManager = PreferencesManager(LocalContext.current)
val searchToken = preferencesManager.getData("token", "")
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>() val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
cartViewModel.getOrders(preferencesManager.getData("user_id", "null")) cartViewModel.getOrders(searchToken)
var unpaidOrder: OrderWithProducts? = cartViewModel.unpaidOrder.observeAsState().value var unpaidOrder: OrderWithProducts? = cartViewModel.unpaidOrder.observeAsState().value
val preparingOrders = cartViewModel.paidOrders.observeAsState().value val paidOrders = cartViewModel.getPaidList(searchToken).collectAsLazyPagingItems()
Box( Box(
modifier = Modifier modifier = Modifier
@ -100,9 +102,9 @@ fun CartWidget(){
.width(340.dp) .width(340.dp)
.height(200.dp) .height(200.dp)
) { ) {
if (preparingOrders != null) { if (paidOrders != null) {
items(preparingOrders.size) { index -> items(paidOrders.itemCount) { index ->
PaidItem(preparingOrders[index]) PaidItem(paidOrders[index]!!)
} }
} }
} }
@ -126,7 +128,7 @@ fun CartWidget(){
modifier = Modifier.size(240.dp, 60.dp), modifier = Modifier.size(240.dp, 60.dp),
onClick = { onClick = {
if (unpaidOrder != null) { if (unpaidOrder != null) {
cartViewModel.payForOrder(unpaidOrder) cartViewModel.payForOrder(searchToken, unpaidOrder)
} }
} }
) { ) {
@ -216,6 +218,8 @@ fun PaidItem(order : OrderWithProducts) {
@Composable @Composable
fun CartItem(order : OrderWithProducts) { fun CartItem(order : OrderWithProducts) {
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>() val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
val preferencesManager = PreferencesManager(LocalContext.current)
val searchToken = preferencesManager.getData("token", "")
Card( Card(
border = BorderStroke(width = 2.dp, color = MyOrange), border = BorderStroke(width = 2.dp, color = MyOrange),
@ -272,7 +276,7 @@ fun CartItem(order : OrderWithProducts) {
.weight(1f) .weight(1f)
.fillMaxSize(0.5f), .fillMaxSize(0.5f),
onClick = { onClick = {
cartViewModel.removeProductFromOrder(order, index) cartViewModel.removeProductFromOrder(searchToken, order, index)
count.value -= 1 count.value -= 1
} }
) { ) {
@ -300,7 +304,7 @@ fun CartItem(order : OrderWithProducts) {
.weight(1f) .weight(1f)
.fillMaxSize(0.5f), .fillMaxSize(0.5f),
onClick = { onClick = {
cartViewModel.addProductToOrder(order, index) cartViewModel.addProductToOrder(searchToken, order, index)
count.value += 1 count.value += 1
} }
) { ) {

View File

@ -4,11 +4,13 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.example.shawarma.data.models.OrderStatus import com.example.shawarma.data.models.OrderStatus
import com.example.shawarma.data.models.OrderWithProducts import com.example.shawarma.data.models.OrderWithProducts
import com.example.shawarma.data.repos.OrderProductRepository import com.example.shawarma.data.repos.OrderProductRepository
import com.example.shawarma.data.repos.OrderRepository import com.example.shawarma.data.repos.OrderRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -20,54 +22,54 @@ class CartViewModel @Inject constructor(
private val _unpaidOrder = MutableLiveData<OrderWithProducts>() private val _unpaidOrder = MutableLiveData<OrderWithProducts>()
val unpaidOrder: LiveData<OrderWithProducts> val unpaidOrder: LiveData<OrderWithProducts>
get() = _unpaidOrder get() = _unpaidOrder
private val _paidOrders = MutableLiveData<List<OrderWithProducts>>()
val paidOrders: LiveData<List<OrderWithProducts>>
get() = _paidOrders
fun getOrders(userId: String) {
// if (userId == "null") return fun getOrders(token: String) {
// viewModelScope.launch { viewModelScope.launch {
// orderRepository.getUnpaidByUser(userId.toInt()).collect { _unpaidOrder.postValue(orderRepository.getUnpaidByUser(token))
// _unpaidOrder.postValue(it) }
// } }
// }
// viewModelScope.launch { fun getPaidList(token: String) : Flow<PagingData<OrderWithProducts>> {
// orderRepository.getPaidByUser(userId.toInt()).collect { return orderRepository.getPaidPaged(token)
// _paidOrders.postValue(it) }
// }
// } fun payForOrder(token: String, order: OrderWithProducts) {
if (order.orderWithProducts.isEmpty()) {
return
} }
fun payForOrder(order: OrderWithProducts) {
val model = order.order val model = order.order
model.status = OrderStatus.Готовится.name model.status = OrderStatus.Готовится.name
viewModelScope.launch { viewModelScope.launch {
orderRepository.update(model) orderRepository.update(token, model)
} }
_unpaidOrder.postValue(null)
} }
fun removeProductFromOrder(order: OrderWithProducts, productId: Int) { fun removeProductFromOrder(token: String, order: OrderWithProducts, productId: Int) {
// val model = order.orderWithProducts[productId].orderProductModel val model = order.orderWithProducts[productId].orderProductModel
// if(model.quantity == 1) { if(model.quantity == 1) {
// // delete // delete
// viewModelScope.launch { viewModelScope.launch {
// orderProductRepository.delete(model) orderProductRepository.delete(token, model)
// } }
// } getOrders(token)
// else{ }
// // update else{
// model.quantity -= 1 // update
// viewModelScope.launch { model.quantity -= 1
// orderProductRepository.update(model) viewModelScope.launch {
// } orderProductRepository.update(token, model)
// } }
}
}
fun addProductToOrder(token: String, order: OrderWithProducts, productId: Int) {
val model = order.orderWithProducts[productId].orderProductModel
// update
model.quantity += 1
viewModelScope.launch {
orderProductRepository.update(token, model)
} }
fun addProductToOrder(order: OrderWithProducts, productId: Int) {
// val model = order.orderWithProducts[productId].orderProductModel
// // update
// model.quantity += 1
// viewModelScope.launch {
// orderProductRepository.update(model)
// }
} }
} }

View File

@ -37,12 +37,12 @@ class OrdersViewModel @Inject constructor(
} }
fun changeOrderStatus(order: OrderWithProducts, newStatus: String) { fun changeOrderStatus(order: OrderWithProducts, newStatus: String) {
val model = order.order // val model = order.order
model.status = newStatus // model.status = newStatus
//
viewModelScope.launch{ // viewModelScope.launch{
orderRepository.update(model) // orderRepository.update(model)
} // }
} }
fun deleteOrder(order: OrderWithProducts) { fun deleteOrder(order: OrderWithProducts) {