Skip to content

Commit a0e116b

Browse files
authored
Merge pull request #12873 from woocommerce/issue/12843-navigate-to-variations-screen
[Woo POS][Non-Simple Products] Navigation to variations screen
2 parents a908f47 + fb44b49 commit a0e116b

File tree

14 files changed

+569
-49
lines changed

14 files changed

+569
-49
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.woocommerce.android.ui.woopos.common.di
2+
3+
import com.woocommerce.android.ui.woopos.home.items.navigation.WooPosItemsNavigator
4+
import dagger.Module
5+
import dagger.Provides
6+
import dagger.hilt.InstallIn
7+
import dagger.hilt.android.components.ActivityRetainedComponent
8+
import dagger.hilt.android.scopes.ActivityRetainedScoped
9+
10+
@InstallIn(ActivityRetainedComponent::class)
11+
@Module
12+
class WooPosActivityProvidesModule {
13+
@ActivityRetainedScoped
14+
@Provides
15+
fun provideLeftPaneNavigator(): WooPosItemsNavigator = WooPosItemsNavigator()
16+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/WooPosHomeScreen.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding
3535
import com.woocommerce.android.ui.woopos.home.WooPosHomeState.ProductsInfoDialog
3636
import com.woocommerce.android.ui.woopos.home.cart.WooPosCartScreen
3737
import com.woocommerce.android.ui.woopos.home.cart.WooPosCartScreenProductsPreview
38-
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsScreen
3938
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsScreenPreview
39+
import com.woocommerce.android.ui.woopos.home.items.navigation.WooPosItemsScreens
4040
import com.woocommerce.android.ui.woopos.home.toolbar.PreviewWooPosFloatingToolbarStatusConnectedWithMenu
4141
import com.woocommerce.android.ui.woopos.home.toolbar.WooPosFloatingToolbar
4242
import com.woocommerce.android.ui.woopos.home.totals.WooPosTotalsScreen
@@ -187,7 +187,7 @@ private fun WooPosHomeScreenProducts(modifier: Modifier) {
187187
if (isPreviewMode()) {
188188
WooPosItemsScreenPreview(modifier)
189189
} else {
190-
WooPosItemsScreen(modifier)
190+
WooPosItemsScreens(modifier = modifier)
191191
}
192192
}
193193

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/WooPosItemNavigationData.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,11 @@ sealed class WooPosItemNavigationData(open val id: Long) {
44
data class SimpleProductData(
55
override val id: Long
66
) : WooPosItemNavigationData(id)
7+
8+
data class VariableProductData(
9+
override val id: Long,
10+
val name: String,
11+
val numOfVariations: Int,
12+
val variationIds: List<Long>
13+
) : WooPosItemNavigationData(id)
714
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/WooPosItemsScreen.kt

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ import androidx.compose.material.IconButton
3232
import androidx.compose.material.MaterialTheme
3333
import androidx.compose.material.Text
3434
import androidx.compose.material.pullrefresh.PullRefreshIndicator
35+
import androidx.compose.material.pullrefresh.PullRefreshState
3536
import androidx.compose.material.pullrefresh.pullRefresh
3637
import androidx.compose.material.pullrefresh.rememberPullRefreshState
3738
import androidx.compose.runtime.Composable
3839
import androidx.compose.runtime.LaunchedEffect
40+
import androidx.compose.runtime.State
3941
import androidx.compose.runtime.collectAsState
4042
import androidx.compose.runtime.derivedStateOf
4143
import androidx.compose.runtime.remember
@@ -73,7 +75,6 @@ import com.woocommerce.android.ui.woopos.common.composeui.toAdaptivePadding
7375
import com.woocommerce.android.ui.woopos.home.items.WooPosItem.SimpleProduct
7476
import com.woocommerce.android.ui.woopos.home.items.WooPosItem.VariableProduct
7577
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsUIEvent.EndOfItemsListReached
76-
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsUIEvent.ItemClicked
7778
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsUIEvent.ProductsLoadingErrorRetryButtonClicked
7879
import com.woocommerce.android.ui.woopos.home.items.WooPosItemsUIEvent.PullToRefreshTriggered
7980
import kotlinx.coroutines.flow.MutableStateFlow
@@ -83,12 +84,18 @@ import kotlinx.coroutines.flow.filter
8384

8485
@OptIn(ExperimentalMaterialApi::class)
8586
@Composable
86-
fun WooPosItemsScreen(modifier: Modifier = Modifier) {
87+
fun WooPosItemsScreen(
88+
modifier: Modifier = Modifier,
89+
listState: LazyListState,
90+
) {
8791
val productsViewModel: WooPosItemsViewModel = hiltViewModel()
8892
WooPosItemsScreen(
8993
modifier = modifier,
9094
itemsStateFlow = productsViewModel.viewState,
91-
onItemClicked = { productsViewModel.onUIEvent(ItemClicked(it)) },
95+
listState,
96+
onItemClicked = { item ->
97+
productsViewModel.onUIEvent(WooPosItemsUIEvent.ItemClicked(item))
98+
},
9299
onEndOfItemListReached = { productsViewModel.onUIEvent(EndOfItemsListReached) },
93100
onPullToRefresh = { productsViewModel.onUIEvent(PullToRefreshTriggered) },
94101
onRetryClicked = { productsViewModel.onUIEvent(ProductsLoadingErrorRetryButtonClicked) },
@@ -109,6 +116,7 @@ fun WooPosItemsScreen(modifier: Modifier = Modifier) {
109116
private fun WooPosItemsScreen(
110117
modifier: Modifier = Modifier,
111118
itemsStateFlow: StateFlow<WooPosItemsViewState>,
119+
listState: LazyListState,
112120
onItemClicked: (item: WooPosItem) -> Unit,
113121
onEndOfItemListReached: () -> Unit,
114122
onPullToRefresh: () -> Unit,
@@ -119,6 +127,35 @@ private fun WooPosItemsScreen(
119127
) {
120128
val state = itemsStateFlow.collectAsState()
121129
val pullToRefreshState = rememberPullRefreshState(state.value.reloadingProductsWithPullToRefresh, onPullToRefresh)
130+
131+
MainItemsList(
132+
modifier = modifier,
133+
pullToRefreshState = pullToRefreshState,
134+
state = state,
135+
listState = listState,
136+
onToolbarInfoIconClicked = onToolbarInfoIconClicked,
137+
onSimpleProductsBannerLearnMoreClicked = onSimpleProductsBannerLearnMoreClicked,
138+
onSimpleProductsBannerClosed = onSimpleProductsBannerClosed,
139+
onItemClicked = onItemClicked,
140+
onEndOfItemListReached = onEndOfItemListReached,
141+
onRetryClicked = onRetryClicked
142+
)
143+
}
144+
145+
@ExperimentalMaterialApi
146+
@Composable
147+
private fun MainItemsList(
148+
modifier: Modifier,
149+
pullToRefreshState: PullRefreshState,
150+
state: State<WooPosItemsViewState>,
151+
listState: LazyListState,
152+
onToolbarInfoIconClicked: () -> Unit,
153+
onSimpleProductsBannerLearnMoreClicked: () -> Unit,
154+
onSimpleProductsBannerClosed: () -> Unit,
155+
onItemClicked: (item: WooPosItem) -> Unit,
156+
onEndOfItemListReached: () -> Unit,
157+
onRetryClicked: () -> Unit
158+
) {
122159
Box(
123160
modifier = modifier
124161
.fillMaxSize()
@@ -154,6 +191,7 @@ private fun WooPosItemsScreen(
154191
)
155192
ItemsList(
156193
itemsState,
194+
listState,
157195
onItemClicked,
158196
onEndOfItemListReached,
159197
)
@@ -249,10 +287,10 @@ private fun SimpleProductsBanner(
249287
@Composable
250288
private fun ItemsList(
251289
state: WooPosItemsViewState.Content,
290+
listState: LazyListState,
252291
onItemClicked: (item: WooPosItem) -> Unit,
253292
onEndOfProductsListReached: () -> Unit,
254293
) {
255-
val listState = rememberLazyListState()
256294
WooPosLazyColumn(
257295
verticalArrangement = Arrangement.spacedBy(8.dp),
258296
contentPadding = PaddingValues(2.dp),
@@ -614,6 +652,7 @@ fun WooPosItemsScreenPreview(modifier: Modifier = Modifier) {
614652
WooPosItemsScreen(
615653
modifier = modifier,
616654
itemsStateFlow = productState,
655+
listState = rememberLazyListState(),
617656
onItemClicked = {},
618657
onEndOfItemListReached = {},
619658
onPullToRefresh = {},
@@ -638,6 +677,7 @@ fun WooPosItemsScreenLoadingPreview() {
638677
WooPosTheme {
639678
WooPosItemsScreen(
640679
itemsStateFlow = productState,
680+
listState = rememberLazyListState(),
641681
onItemClicked = {},
642682
onEndOfItemListReached = {},
643683
onPullToRefresh = {},
@@ -657,6 +697,7 @@ fun WooPosProductsScreenEmptyListPreview() {
657697
WooPosTheme {
658698
WooPosItemsScreen(
659699
itemsStateFlow = productState,
700+
listState = rememberLazyListState(),
660701
onItemClicked = {},
661702
onEndOfItemListReached = {},
662703
onPullToRefresh = {},
@@ -676,6 +717,7 @@ fun WooPosProductsScreenErrorPreview() {
676717
WooPosTheme {
677718
WooPosItemsScreen(
678719
itemsStateFlow = productState,
720+
listState = rememberLazyListState(),
679721
onItemClicked = {},
680722
onEndOfItemListReached = {},
681723
onPullToRefresh = {},
@@ -728,6 +770,7 @@ fun WooPosHomeScreenItemsWithSimpleProductsOnlyBannerPreview() {
728770
WooPosTheme {
729771
WooPosItemsScreen(
730772
itemsStateFlow = productState,
773+
listState = rememberLazyListState(),
731774
onItemClicked = {},
732775
onEndOfItemListReached = {},
733776
onPullToRefresh = {},
@@ -780,6 +823,7 @@ fun WooPosHomeScreenItemsWithInfoIconInToolbarPreview() {
780823
WooPosTheme {
781824
WooPosItemsScreen(
782825
itemsStateFlow = productState,
826+
listState = rememberLazyListState(),
783827
onItemClicked = {},
784828
onEndOfItemListReached = {},
785829
onPullToRefresh = {},

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/WooPosItemsUIEvent.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ sealed class WooPosItemsUIEvent {
88
data object SimpleProductsBannerClosed : WooPosItemsUIEvent()
99
data object SimpleProductsBannerLearnMoreClicked : WooPosItemsUIEvent()
1010
data object SimpleProductsDialogInfoIconClicked : WooPosItemsUIEvent()
11+
data object BackButtonClicked : WooPosItemsUIEvent()
1112
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/WooPosItemsViewModel.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.woocommerce.android.ui.woopos.home.ChildToParentEvent
99
import com.woocommerce.android.ui.woopos.home.WooPosChildrenToParentEventSender
1010
import com.woocommerce.android.ui.woopos.home.items.WooPosItem.SimpleProduct
1111
import com.woocommerce.android.ui.woopos.home.items.WooPosItem.VariableProduct
12+
import com.woocommerce.android.ui.woopos.home.items.navigation.WooPosItemsNavigator
1213
import com.woocommerce.android.ui.woopos.home.items.products.WooPosProductsDataSource
1314
import com.woocommerce.android.ui.woopos.util.datastore.WooPosPreferencesRepository
1415
import com.woocommerce.android.ui.woopos.util.format.WooPosFormatPrice
@@ -29,6 +30,7 @@ class WooPosItemsViewModel @Inject constructor(
2930
private val fromChildToParentEventSender: WooPosChildrenToParentEventSender,
3031
private val priceFormat: WooPosFormatPrice,
3132
private val preferencesRepository: WooPosPreferencesRepository,
33+
private val navigator: WooPosItemsNavigator,
3234
) : ViewModel() {
3335
private var loadMoreProductsJob: Job? = null
3436

@@ -87,6 +89,18 @@ class WooPosItemsViewModel @Inject constructor(
8789
WooPosItemsUIEvent.SimpleProductsDialogInfoIconClicked -> {
8890
onSimpleProductsDialogInfoClicked()
8991
}
92+
93+
WooPosItemsUIEvent.BackButtonClicked -> {
94+
navigateBackToItemListScreen()
95+
}
96+
}
97+
}
98+
99+
private fun navigateBackToItemListScreen() {
100+
viewModelScope.launch {
101+
navigator.sendNavigationEvent(
102+
WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen
103+
)
90104
}
91105
}
92106

@@ -101,6 +115,18 @@ class WooPosItemsViewModel @Inject constructor(
101115
}
102116

103117
is VariableProduct -> {
118+
viewModelScope.launch {
119+
navigator.sendNavigationEvent(
120+
WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateToVariationsScreen(
121+
WooPosItemNavigationData.VariableProductData(
122+
id = event.item.id,
123+
name = event.item.name,
124+
numOfVariations = event.item.numOfVariations,
125+
variationIds = event.item.variationIds
126+
)
127+
)
128+
)
129+
}
104130
}
105131
}
106132
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.woocommerce.android.ui.woopos.home.items.navigation
2+
3+
import com.woocommerce.android.ui.woopos.home.items.WooPosItemNavigationData.VariableProductData
4+
import kotlinx.coroutines.flow.MutableSharedFlow
5+
import kotlinx.coroutines.flow.asSharedFlow
6+
import javax.inject.Inject
7+
8+
class WooPosItemsNavigator @Inject constructor() {
9+
private val _events = MutableSharedFlow<WooPosItemsScreenNavigationEvent>()
10+
val events = _events.asSharedFlow()
11+
12+
suspend fun sendNavigationEvent(event: WooPosItemsScreenNavigationEvent) {
13+
_events.emit(event)
14+
}
15+
16+
sealed class WooPosItemsScreenNavigationEvent {
17+
data class NavigateToVariationsScreen(val product: VariableProductData) : WooPosItemsScreenNavigationEvent()
18+
data object NavigateBackToItemListScreen : WooPosItemsScreenNavigationEvent()
19+
}
20+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.woocommerce.android.ui.woopos.home.items.navigation
2+
3+
import androidx.lifecycle.ViewModel
4+
import androidx.lifecycle.viewModelScope
5+
import com.woocommerce.android.ui.woopos.home.items.WooPosItemNavigationData.VariableProductData
6+
import dagger.hilt.android.lifecycle.HiltViewModel
7+
import kotlinx.coroutines.flow.MutableStateFlow
8+
import kotlinx.coroutines.flow.StateFlow
9+
import kotlinx.coroutines.launch
10+
import javax.inject.Inject
11+
12+
@HiltViewModel
13+
class WooPosItemsScreenViewModel @Inject constructor(
14+
private val navigator: WooPosItemsNavigator,
15+
) : ViewModel() {
16+
private val _screenState = MutableStateFlow<ItemsScreens>(ItemsScreens.ItemListScreen)
17+
val screenState: StateFlow<ItemsScreens> = _screenState
18+
19+
init {
20+
viewModelScope.launch {
21+
listenToNavigationEvents()
22+
}
23+
}
24+
25+
private fun navigateToVariationsScreen(product: VariableProductData) {
26+
_screenState.value = ItemsScreens.VariationsScreen(product)
27+
}
28+
29+
private fun navigateBackToItemListScreen() {
30+
_screenState.value = ItemsScreens.ItemListScreen
31+
}
32+
33+
private suspend fun listenToNavigationEvents() {
34+
navigator.events.collect {
35+
when (it) {
36+
is WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateToVariationsScreen -> {
37+
navigateToVariationsScreen(it.product)
38+
}
39+
is WooPosItemsNavigator.WooPosItemsScreenNavigationEvent.NavigateBackToItemListScreen -> {
40+
navigateBackToItemListScreen()
41+
}
42+
}
43+
}
44+
}
45+
46+
fun onUiEvent(wooPosLeftPaneScreensNavigationEvent: WooPosItemsNavigator.WooPosItemsScreenNavigationEvent) {
47+
viewModelScope.launch {
48+
navigator.sendNavigationEvent(wooPosLeftPaneScreensNavigationEvent)
49+
}
50+
}
51+
52+
sealed class ItemsScreens {
53+
data object ItemListScreen : ItemsScreens()
54+
data class VariationsScreen(val product: VariableProductData) : ItemsScreens()
55+
}
56+
}

0 commit comments

Comments
 (0)