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

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
@Singleton
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

View File

@ -1,5 +1,6 @@
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.OrderProductRemote
import com.example.shawarma.data.api.models.ProductListResponse
@ -77,9 +78,15 @@ interface MyServerService {
@GET("order/unpaid")
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")
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
//
@ -90,6 +97,9 @@ interface MyServerService {
@PUT("order/product")
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 {
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()
)
@Serializable
data class OrderListResponse(
val orders: List<OrderModelRemote> = listOf(),
val nextKey: Int? = null
)
fun OrderModelRemote.toOrderModel() : OrderModel = OrderModel(
id, status, user_id, date = date
)

View File

@ -14,4 +14,8 @@ class RestOrderProductRepository @Inject constructor(
suspend fun updateOrderProduct(token: String, orderProduct: OrderProductRemote) {
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? {
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
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
@ -19,11 +20,40 @@ interface OrderDao {
@Query("select * from orders")
fun getAll(): Flow<List<OrderWithProducts>>
@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")
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>>
@Query("select * from orders where orders.user_id =:userId and orders.order_status = 'Неоплачено'")
fun getUnpaidByUser(userId: Int) : Flow<OrderWithProducts>
@Query("select * from orders where orders.user_id =:userId and (orders.order_status = 'Готовится' or orders.order_status = 'Готово')")
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)
return restOrderProductRepository.updateOrderProduct(token, orderProduct.toOrderProductRemote())
}
suspend fun delete(order: OrderProductModel) {
return orderProductDao.delete(order)
suspend fun delete(token: String, orderProduct: OrderProductModel) {
orderProductDao.delete(orderProduct)
restOrderProductRepository.deleteOrderProduct(token, orderProduct.toOrderProductRemote())
}
}

View File

@ -1,10 +1,16 @@
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.toOrderModelRemote
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.db.AppDatabase
import com.example.shawarma.data.interfaces.dao.OrderDao
import com.example.shawarma.data.interfaces.dao.OrderProductDao
import com.example.shawarma.data.interfaces.dao.ProductDao
@ -15,20 +21,23 @@ import kotlinx.coroutines.flow.first
import javax.inject.Inject
class OrderRepository @Inject constructor(
private val database: AppDatabase,
private val orderDao: OrderDao,
private val productDao: ProductDao,
private val orderProductDao: OrderProductDao,
private val restRepository: RestOrderRepository
){
suspend fun insert(token: String, order: OrderModel): OrderModel? {
orderDao.insert(order)
val result = restRepository.insertOrder(token, order.toOrderModelRemote())
if (result == null) {
return result
}
return result.toOrderModel()
}
suspend fun update(order:OrderModel) {
return orderDao.update(order)
suspend fun update(token: String, order:OrderModel) {
orderDao.update(order)
restRepository.updateOrder(token, order.toOrderModelRemote())
}
suspend fun delete(order: OrderModel) {
return orderDao.delete(order)
@ -36,7 +45,7 @@ class OrderRepository @Inject constructor(
fun getAll(): Flow<List<OrderWithProducts>> {
return orderDao.getAll()
}
fun getById(id: Int): Flow<List<OrderWithProducts>> {
fun getById(id: Int): Flow<OrderWithProducts>{
return orderDao.getById(id)
}
fun getByUserId(userId: Int): Flow<List<OrderWithProducts>> {
@ -44,14 +53,16 @@ class OrderRepository @Inject constructor(
}
suspend fun getUnpaidByUser(token: String) : OrderWithProducts? {
val order = restRepository.getUnpaidOrder(token)
if (orderDao.getUnpaidByUser(order.user_id!!).first() != null) {
return orderDao.getUnpaidByUser(order.user_id!!).first()
if (order!!.id == null) {
return null
}
if (orderDao.getById(order.id!!).first() != null) {
orderDao.delete(order.toOrderModel())
}
if (order!!.id != null) {
orderDao.insert(order.toOrderModel())
for (product in order.order_products) {
orderProductDao.insert(product.toOrderProductModel())
productDao.insert(product.product!!.toProductModel())
}
return orderDao.getUnpaidByUser(order.user_id!!).first()
}
@ -60,4 +71,15 @@ class OrderRepository @Inject constructor(
fun getPaidByUser(userId: Int) : Flow<List<OrderWithProducts>> {
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.zIndex
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import com.example.shawarma.data.models.OrderWithProducts
import com.example.shawarma.data.sharedpref.PreferencesManager
import com.example.shawarma.ui.theme.MarckFamily
@ -59,12 +60,13 @@ fun CartScreen() {
@Composable
fun CartWidget(){
val preferencesManager = PreferencesManager(LocalContext.current)
val searchToken = preferencesManager.getData("token", "")
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
cartViewModel.getOrders(preferencesManager.getData("user_id", "null"))
cartViewModel.getOrders(searchToken)
var unpaidOrder: OrderWithProducts? = cartViewModel.unpaidOrder.observeAsState().value
val preparingOrders = cartViewModel.paidOrders.observeAsState().value
val paidOrders = cartViewModel.getPaidList(searchToken).collectAsLazyPagingItems()
Box(
modifier = Modifier
@ -100,9 +102,9 @@ fun CartWidget(){
.width(340.dp)
.height(200.dp)
) {
if (preparingOrders != null) {
items(preparingOrders.size) { index ->
PaidItem(preparingOrders[index])
if (paidOrders != null) {
items(paidOrders.itemCount) { index ->
PaidItem(paidOrders[index]!!)
}
}
}
@ -126,7 +128,7 @@ fun CartWidget(){
modifier = Modifier.size(240.dp, 60.dp),
onClick = {
if (unpaidOrder != null) {
cartViewModel.payForOrder(unpaidOrder)
cartViewModel.payForOrder(searchToken, unpaidOrder)
}
}
) {
@ -216,6 +218,8 @@ fun PaidItem(order : OrderWithProducts) {
@Composable
fun CartItem(order : OrderWithProducts) {
val cartViewModel: CartViewModel = hiltViewModel<CartViewModel>()
val preferencesManager = PreferencesManager(LocalContext.current)
val searchToken = preferencesManager.getData("token", "")
Card(
border = BorderStroke(width = 2.dp, color = MyOrange),
@ -272,7 +276,7 @@ fun CartItem(order : OrderWithProducts) {
.weight(1f)
.fillMaxSize(0.5f),
onClick = {
cartViewModel.removeProductFromOrder(order, index)
cartViewModel.removeProductFromOrder(searchToken, order, index)
count.value -= 1
}
) {
@ -300,7 +304,7 @@ fun CartItem(order : OrderWithProducts) {
.weight(1f)
.fillMaxSize(0.5f),
onClick = {
cartViewModel.addProductToOrder(order, index)
cartViewModel.addProductToOrder(searchToken, order, index)
count.value += 1
}
) {

View File

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

View File

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