diff --git a/app/src/main/java/com/example/shawarma/AppModule.kt b/app/src/main/java/com/example/shawarma/AppModule.kt index ca85657..49dbb3e 100644 --- a/app/src/main/java/com/example/shawarma/AppModule.kt +++ b/app/src/main/java/com/example/shawarma/AppModule.kt @@ -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 diff --git a/app/src/main/java/com/example/shawarma/data/api/MyServerService.kt b/app/src/main/java/com/example/shawarma/data/api/MyServerService.kt index 5813de9..3fc9653 100644 --- a/app/src/main/java/com/example/shawarma/data/api/MyServerService.kt +++ b/app/src/main/java/com/example/shawarma/data/api/MyServerService.kt @@ -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/" diff --git a/app/src/main/java/com/example/shawarma/data/api/mediators/OrderRemoteMediator.kt b/app/src/main/java/com/example/shawarma/data/api/mediators/OrderRemoteMediator.kt new file mode 100644 index 0000000..032c626 --- /dev/null +++ b/app/src/main/java/com/example/shawarma/data/api/mediators/OrderRemoteMediator.kt @@ -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(){ + + private val orderDao = database.orderDao() + + override suspend fun load( + loadType: LoadType, + state: PagingState + ): 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() + for (order in response.orders) { + orders.add(order.toOrderModel()) + } + orderDao.insertAll(orders) + } + + MediatorResult.Success(endOfPaginationReached = response.nextKey == -1) + } catch (e: IOException) { + MediatorResult.Error(e) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/data/api/models/OrderModelRemote.kt b/app/src/main/java/com/example/shawarma/data/api/models/OrderModelRemote.kt index 244ba5d..57c6c59 100644 --- a/app/src/main/java/com/example/shawarma/data/api/models/OrderModelRemote.kt +++ b/app/src/main/java/com/example/shawarma/data/api/models/OrderModelRemote.kt @@ -13,6 +13,12 @@ data class OrderModelRemote( val order_products: List = listOf() ) +@Serializable +data class OrderListResponse( + val orders: List = listOf(), + val nextKey: Int? = null +) + fun OrderModelRemote.toOrderModel() : OrderModel = OrderModel( id, status, user_id, date = date ) diff --git a/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderProductRepository.kt b/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderProductRepository.kt index aa52688..e9b99ef 100644 --- a/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderProductRepository.kt +++ b/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderProductRepository.kt @@ -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) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderRepository.kt b/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderRepository.kt index b630b29..2c3a965 100644 --- a/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderRepository.kt +++ b/app/src/main/java/com/example/shawarma/data/api/repos/RestOrderRepository.kt @@ -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) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/data/interfaces/dao/OrderDao.kt b/app/src/main/java/com/example/shawarma/data/interfaces/dao/OrderDao.kt index c4631d2..45779ef 100644 --- a/app/src/main/java/com/example/shawarma/data/interfaces/dao/OrderDao.kt +++ b/app/src/main/java/com/example/shawarma/data/interfaces/dao/OrderDao.kt @@ -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> @Query("select * from orders where orders.id =:id") - fun getById(id: Int): Flow> + fun getById(id: Int): Flow @Query("select * from orders where orders.user_id =:userId") fun getByUserId(userId: Int): Flow> @Query("select * from orders where orders.user_id =:userId and orders.order_status = 'Неоплачено'") fun getUnpaidByUser(userId: Int) : Flow @Query("select * from orders where orders.user_id =:userId and (orders.order_status = 'Готовится' or orders.order_status = 'Готово')") fun getPaidByUser(userId: Int) : Flow> + + suspend fun insertAll(orders: List) { + for (order in orders) { + insert(order) + } + } + + @Query("select * from orders where orders.order_status != 'Неоплачено'") + fun getPaidPaged(): PagingSource + + @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() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/data/repos/OrderProductRepository.kt b/app/src/main/java/com/example/shawarma/data/repos/OrderProductRepository.kt index f19e3be..51587d5 100644 --- a/app/src/main/java/com/example/shawarma/data/repos/OrderProductRepository.kt +++ b/app/src/main/java/com/example/shawarma/data/repos/OrderProductRepository.kt @@ -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()) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/data/repos/OrderRepository.kt b/app/src/main/java/com/example/shawarma/data/repos/OrderRepository.kt index 899e550..df4f48e 100644 --- a/app/src/main/java/com/example/shawarma/data/repos/OrderRepository.kt +++ b/app/src/main/java/com/example/shawarma/data/repos/OrderRepository.kt @@ -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> { return orderDao.getAll() } - fun getById(id: Int): Flow> { + fun getById(id: Int): Flow{ return orderDao.getById(id) } fun getByUserId(userId: Int): Flow> { @@ -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> { return orderDao.getPaidByUser(userId) } + + @OptIn(ExperimentalPagingApi::class) + fun getPaidPaged(token: String): Flow> = Pager( + config = PagingConfig( + pageSize = 6, + enablePlaceholders = false + ), + pagingSourceFactory = orderDao::getPaidPaged, + remoteMediator = OrderRemoteMediator(database = database, serverService = MyServerService.getInstance(), query = "paid", token = token) + ).flow + } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/screens/cart/CartScreen.kt b/app/src/main/java/com/example/shawarma/screens/cart/CartScreen.kt index 834d333..5ec1d97 100644 --- a/app/src/main/java/com/example/shawarma/screens/cart/CartScreen.kt +++ b/app/src/main/java/com/example/shawarma/screens/cart/CartScreen.kt @@ -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.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() + 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 } ) { diff --git a/app/src/main/java/com/example/shawarma/viewmodels/CartViewModel.kt b/app/src/main/java/com/example/shawarma/viewmodels/CartViewModel.kt index 31ed735..df06371 100644 --- a/app/src/main/java/com/example/shawarma/viewmodels/CartViewModel.kt +++ b/app/src/main/java/com/example/shawarma/viewmodels/CartViewModel.kt @@ -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() val unpaidOrder: LiveData get() = _unpaidOrder - private val _paidOrders = MutableLiveData>() - val paidOrders: LiveData> - 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> { + 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) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/shawarma/viewmodels/OrdersViewModel.kt b/app/src/main/java/com/example/shawarma/viewmodels/OrdersViewModel.kt index 5a54287..f02675f 100644 --- a/app/src/main/java/com/example/shawarma/viewmodels/OrdersViewModel.kt +++ b/app/src/main/java/com/example/shawarma/viewmodels/OrdersViewModel.kt @@ -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) {