diff --git a/client_restaurant/shared/src/commonMain/kotlin/di/GatewayModule.kt b/client_restaurant/shared/src/commonMain/kotlin/di/GatewayModule.kt index 7ebb335b3..7c54a2a2e 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/di/GatewayModule.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/di/GatewayModule.kt @@ -15,6 +15,7 @@ import domain.gateway.remote.IRestaurantRemoteGateway import org.koin.core.module.dsl.bind import org.koin.core.module.dsl.singleOf import org.koin.dsl.module +import data.gateway.remote.pagesource.OrdersHistoryPagingSource val GatewayModule = module { // singleOf(::FakeRemoteGateWay) { bind() } @@ -24,5 +25,7 @@ val GatewayModule = module { singleOf(::IdentityRemoteGateway) { bind() } singleOf(::OrderRemoteGateway) { bind() } singleOf(::RestaurantRemoteGateWay) { bind() } + singleOf(::OrdersHistoryPagingSource) + } \ No newline at end of file diff --git a/client_restaurant/shared/src/commonMain/kotlin/domain/usecase/ManageOrderUseCase.kt b/client_restaurant/shared/src/commonMain/kotlin/domain/usecase/ManageOrderUseCase.kt index 6d9cbc2e3..00cf65b27 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/domain/usecase/ManageOrderUseCase.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/domain/usecase/ManageOrderUseCase.kt @@ -1,6 +1,10 @@ package domain.usecase import domain.entity.AddressInfo +import androidx.paging.Pager +import androidx.paging.PagingConfig +import androidx.paging.PagingData +import data.gateway.remote.pagesource.OrdersHistoryPagingSource import domain.entity.Order import domain.entity.Trip import domain.gateway.remote.IOrderRemoteGateway @@ -13,7 +17,8 @@ interface IManageOrderUseCase { suspend fun cancelOrder(orderId: String): Order suspend fun getAddressInfo(userId: String): AddressInfo suspend fun createOrderTrip(trip: Trip): Trip - suspend fun getOrdersHistory(restaurantId: String, page: Int, limit: Int): List + suspend fun getOrdersHistory(restaurantId: String): Flow> + suspend fun getOrdersRevenueByDaysBefore( restaurantId: String, daysBack: Int, @@ -25,13 +30,17 @@ interface IManageOrderUseCase { ): List> } -class ManageOrderUseCase(private val orderRemoteGateway: IOrderRemoteGateway) : +class ManageOrderUseCase( + private val orderRemoteGateway: IOrderRemoteGateway, + private val ordersHistoryPagingSource: OrdersHistoryPagingSource +) : IManageOrderUseCase { - override suspend fun getCurrentOrders(restaurantId: String): Flow{ - return orderRemoteGateway.getCurrentOrders(restaurantId) + override suspend fun getCurrentOrders(restaurantId: String): Flow { + return orderRemoteGateway.getCurrentOrders(restaurantId) } - override suspend fun getActiveOrders(restaurantId: String): List{ - return orderRemoteGateway.getActiveOrders(restaurantId) + + override suspend fun getActiveOrders(restaurantId: String): List { + return orderRemoteGateway.getActiveOrders(restaurantId) } override suspend fun updateOrderState(orderId: String): Order { @@ -42,6 +51,13 @@ class ManageOrderUseCase(private val orderRemoteGateway: IOrderRemoteGateway) : return orderRemoteGateway.cancelOrder(orderId) } + override suspend fun getOrdersHistory(restaurantId: String): Flow> { + ordersHistoryPagingSource.initOrders(restaurantId) + return Pager( + config = PagingConfig(pageSize = 10), + pagingSourceFactory = { ordersHistoryPagingSource }, + ).flow + } override suspend fun getAddressInfo(userId: String): AddressInfo { return orderRemoteGateway.getAddressInfo(userId) } @@ -50,16 +66,6 @@ class ManageOrderUseCase(private val orderRemoteGateway: IOrderRemoteGateway) : return orderRemoteGateway.createOrderTrip(trip) } - override suspend fun getOrdersHistory( - restaurantId: String, - page: Int, - limit: Int - ): List { - val result = orderRemoteGateway.getOrdersHistory(restaurantId, page, limit) - println("getOrdersHistory from use case: ${result}") - return result.items - } - override suspend fun getOrdersRevenueByDaysBefore( restaurantId: String, daysBack: Int, diff --git a/client_restaurant/shared/src/commonMain/kotlin/presentation/mealManagement/composable/CuisineBottomSheetContent.kt b/client_restaurant/shared/src/commonMain/kotlin/presentation/mealManagement/composable/CuisineBottomSheetContent.kt index d3cc2b22e..068f161db 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/presentation/mealManagement/composable/CuisineBottomSheetContent.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/presentation/mealManagement/composable/CuisineBottomSheetContent.kt @@ -23,6 +23,7 @@ import com.beepbeep.designSystem.ui.theme.Theme import presentation.mealManagement.CuisineUIState import presentation.mealManagement.MealScreenInteractionListener import resources.Resources +import util.getNavigationBarPadding @OptIn(ExperimentalFoundationApi::class) @Composable @@ -33,7 +34,11 @@ fun CuisineBottomSheet( ) { LazyColumn( modifier = modifier.fillMaxWidth().heightIn(max = 320.dp) - .padding(top = Theme.dimens.space16).padding(horizontal = Theme.dimens.space16) + + .padding( + top = Theme.dimens.space16, + bottom = getNavigationBarPadding().calculateBottomPadding() + ).padding(horizontal = Theme.dimens.space16) ) { stickyHeader { diff --git a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/Mappers.kt b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/Mappers.kt index bab392143..a95a71a19 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/Mappers.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/Mappers.kt @@ -1,8 +1,15 @@ package presentation.orderHistory +import androidx.paging.PagingData +import androidx.paging.map +import domain.entity.Meal import domain.entity.Order +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import presentation.mealManagement.toUIState import presentation.order.OrderUiState import presentation.order.toOrderMealUiState +import presentation.order.toOrderUiState import util.formatDateTime @@ -14,4 +21,8 @@ fun Order.toOrderHistoryUiState(): OrderUiState { totalPrice = totalPrice, createdAt = createdAt.formatDateTime(), ) +} + +fun Flow>.toUIState(): Flow> { + return this.map { pagingData -> pagingData.map { it.toOrderHistoryUiState()} } } \ No newline at end of file diff --git a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenModel.kt b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenModel.kt index 45f9e65e9..497e505f3 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenModel.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenModel.kt @@ -1,10 +1,15 @@ package presentation.orderHistory +import androidx.paging.PagingData +import androidx.paging.filter +import androidx.paging.map import cafe.adriel.voyager.core.model.coroutineScope import domain.entity.Order import domain.entity.OrderStatus import domain.usecase.IManageOrderUseCase import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map import presentation.base.BaseScreenModel import presentation.base.ErrorState @@ -22,22 +27,30 @@ class OrderHistoryScreenModel( private fun getData() { updateState { it.copy(isLoading = true) } tryToExecute( - ::getOrdersHistory, ::onGetOrdersHistorySuccess, ::onError + { ordersManagement.getOrdersHistory(restaurantId) }, + ::onGetOrdersHistorySuccess, + ::onError ) } - private suspend fun getOrdersHistory(): List { - return ordersManagement.getOrdersHistory(restaurantId, 1, 10)//todo just for testing - } + private fun onGetOrdersHistorySuccess(orders: Flow>) { + val ordersUiState = orders.map { pagingData -> + pagingData.map { order -> order.toOrderHistoryUiState() } + } - private fun onGetOrdersHistorySuccess(orders: List) { - val ordersUiState = orders.map { it.toOrderHistoryUiState() } updateState { currentState -> - currentState.copy(isLoading = false, + currentState.copy( + isLoading = false, orders = ordersUiState, - currentOrders = ordersUiState.filter { - currentState.selectedType == OrderHistoryScreenUiState.OrderSelectType.FINISHED && it.orderState == OrderStatus.DONE || currentState.selectedType == OrderHistoryScreenUiState.OrderSelectType.CANCELLED && it.orderState == OrderStatus.CANCELED - }) + currentOrders = ordersUiState.map { pagingData -> + pagingData.filter { + currentState.selectedType == OrderHistoryScreenUiState.OrderSelectType.FINISHED + && it.orderState == OrderStatus.DONE + || currentState.selectedType == OrderHistoryScreenUiState.OrderSelectType.CANCELLED + && it.orderState == OrderStatus.CANCELED + } + } + ) } } @@ -53,11 +66,13 @@ class OrderHistoryScreenModel( updateState { currentState -> currentState.copy( selectedType = type, - currentOrders = currentState.orders.filter { - type == OrderHistoryScreenUiState.OrderSelectType.FINISHED && - it.orderState == OrderStatus.DONE || - type == OrderHistoryScreenUiState.OrderSelectType.CANCELLED - && it.orderState == OrderStatus.CANCELED + currentOrders = currentState.orders.map { pagingData -> + pagingData.filter { + type == OrderHistoryScreenUiState.OrderSelectType.FINISHED + && it.orderState == OrderStatus.DONE || + type == OrderHistoryScreenUiState.OrderSelectType.CANCELLED && + it.orderState == OrderStatus.CANCELED + } } ) } diff --git a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenUiState.kt b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenUiState.kt index d782d4932..4b569bc76 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenUiState.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrderHistoryScreenUiState.kt @@ -1,12 +1,15 @@ package presentation.orderHistory +import androidx.paging.PagingData +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow import presentation.base.ErrorState import presentation.order.OrderUiState data class OrderHistoryScreenUiState( val isLoading: Boolean = false, - val orders: List = emptyList(), - val currentOrders: List = emptyList(), + val orders:Flow> = emptyFlow(), + val currentOrders: Flow> = emptyFlow(), val selectedType: OrderSelectType = OrderSelectType.FINISHED, val errorState: ErrorState? = null ) { diff --git a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrdersHistoryScreen.kt b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrdersHistoryScreen.kt index d75199beb..db1fc01b0 100644 --- a/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrdersHistoryScreen.kt +++ b/client_restaurant/shared/src/commonMain/kotlin/presentation/orderHistory/OrdersHistoryScreen.kt @@ -26,6 +26,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.unit.dp +import app.cash.paging.LoadStateNotLoading +import app.cash.paging.compose.collectAsLazyPagingItems import cafe.adriel.voyager.navigator.Navigator import com.beepbeep.designSystem.ui.composable.BpAnimatedTabLayout import com.beepbeep.designSystem.ui.composable.modifier.shimmerEffect @@ -87,6 +89,7 @@ class OrdersHistoryScreen(private val restaurantId: String) : state: OrderHistoryScreenUiState, listener: OrderHistoryScreenInteractionListener ) { + val orders = state.orders.collectAsLazyPagingItems() LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Adaptive(300.dp), contentPadding = PaddingValues(16.dp), @@ -114,23 +117,25 @@ class OrdersHistoryScreen(private val restaurantId: String) : ) } } - items(state.currentOrders, key = { it.orderId }) { order -> - OrderCard( - order = order, - modifier = Modifier - ) { - Text( - order.createdAt, - style = Theme.typography.caption.copy(color = Theme.colors.contentTertiary), - ) + items(items = orders.itemSnapshotList, key = { it?.orderId ?: "" }) { order -> + order?.let { + OrderCard( + order = it, + modifier = Modifier + ) { + Text( + order.createdAt, + style = Theme.typography.caption.copy(color = Theme.colors.contentTertiary), + ) + } } + } } - NoItemsPlaceholder( painter = painterResource(Resources.images.emptyScreen), text = Resources.strings.noOrderHistory, - isVisible = (state.orders.isEmpty()), + isVisible = (orders.loadState.refresh is LoadStateNotLoading && orders.itemCount < 1), ) }