Skip to content

Commit 70a8e89

Browse files
authored
Merge branch 'trunk' into woomob-1573-woo-poslocal-catalog-getfrommemoryincache-uses-store
2 parents 4924b6c + 9f3beef commit 70a8e89

File tree

22 files changed

+567
-181
lines changed

22 files changed

+567
-181
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/compose/BookingAttendanceStatusBottomSheet.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.woocommerce.android.ui.bookings.compose
22

33
import androidx.compose.foundation.clickable
44
import androidx.compose.foundation.layout.Arrangement
5+
import androidx.compose.foundation.layout.Box
56
import androidx.compose.foundation.layout.Column
67
import androidx.compose.foundation.layout.Row
78
import androidx.compose.foundation.layout.Spacer
@@ -34,6 +35,7 @@ fun BookingAttendanceStatusBottomSheet(
3435
onSelect: (BookingAttendanceStatus) -> Unit,
3536
onDismiss: () -> Unit,
3637
modifier: Modifier = Modifier,
38+
selected: BookingAttendanceStatus? = null,
3739
) {
3840
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
3941
val scope = rememberCoroutineScope()
@@ -48,6 +50,7 @@ fun BookingAttendanceStatusBottomSheet(
4850
onSelect(status)
4951
onDismiss()
5052
},
53+
selected = selected,
5154
modifier = modifier
5255
)
5356
}
@@ -57,6 +60,7 @@ fun BookingAttendanceStatusBottomSheet(
5760
private fun BookingAttendanceStatusSelection(
5861
onSelect: (BookingAttendanceStatus) -> Unit,
5962
modifier: Modifier = Modifier,
63+
selected: BookingAttendanceStatus? = null,
6064
) {
6165
Column(
6266
modifier = modifier
@@ -74,9 +78,10 @@ private fun BookingAttendanceStatusSelection(
7478
BookingAttendanceStatus.Booked,
7579
BookingAttendanceStatus.CheckedIn,
7680
BookingAttendanceStatus.NoShow,
77-
).forEachIndexed { index, status ->
81+
).forEach { status ->
7882
AttendanceStatusRow(
7983
status = status,
84+
isSelected = status == selected,
8085
onClick = { onSelect(status) }
8186
)
8287
}
@@ -86,6 +91,7 @@ private fun BookingAttendanceStatusSelection(
8691
@Composable
8792
private fun AttendanceStatusRow(
8893
status: BookingAttendanceStatus,
94+
isSelected: Boolean,
8995
onClick: () -> Unit,
9096
) {
9197
Row(
@@ -117,6 +123,15 @@ private fun AttendanceStatusRow(
117123
color = MaterialTheme.colorScheme.onSurfaceVariant
118124
)
119125
}
126+
Box(Modifier.size(26.dp)) {
127+
if (isSelected) {
128+
Icon(
129+
painter = painterResource(id = R.drawable.ic_done_secondary),
130+
contentDescription = stringResource(R.string.bookings_filters_selected_option_content_description),
131+
tint = MaterialTheme.colorScheme.primary
132+
)
133+
}
134+
}
120135
}
121136
}
122137

@@ -152,6 +167,7 @@ private fun AttendanceStatusRowPreview() {
152167
WooThemeWithBackground {
153168
AttendanceStatusRow(
154169
status = BookingAttendanceStatus.CheckedIn,
170+
isSelected = false,
155171
onClick = {}
156172
)
157173
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/details/BookingDetailsScreen.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ fun BookingDetailsScreen(
130130
onSelect = { status ->
131131
viewState.bookingUiState.onAttendanceStatusSelected(status)
132132
},
133-
onDismiss = { showAttendanceSheet.value = false }
133+
onDismiss = { showAttendanceSheet.value = false },
134+
selected = viewState.bookingUiState.bookingSummary.attendanceStatus
134135
)
135136
}
136137
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ import androidx.navigation.compose.NavHost
2828
import androidx.navigation.compose.composable
2929
import androidx.navigation.compose.rememberNavController
3030
import com.woocommerce.android.R
31+
import com.woocommerce.android.ui.bookings.filter.customer.BookingCustomerFilterPage
3132
import com.woocommerce.android.ui.bookings.filter.type.BookingTypeFilterRoute
33+
import com.woocommerce.android.ui.compose.Render
3234
import com.woocommerce.android.ui.compose.component.Toolbar
3335
import com.woocommerce.android.ui.compose.component.WCColoredButton
3436
import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews
3537
import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground
38+
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption
3639

3740
@Composable
3841
fun BookingFilterListScreen(state: BookingFilterListUiState) {
@@ -73,6 +76,8 @@ fun BookingFilterListScreen(state: BookingFilterListUiState) {
7376
.padding(innerPadding)
7477
)
7578

79+
state.dialogState?.Render()
80+
7681
// The navigation is driven by the state, so we handle back navigation by calling onClose
7782
// We need to ensure that this called after NavHost to make sure we receive back events
7883
BackHandler {
@@ -128,7 +133,18 @@ private fun FiltersNavHost(
128133
}
129134
}
130135
composable(BookingFilterPage.Customer.route) {
131-
TODO()
136+
BookingCustomerFilterPage { customer ->
137+
customer.customerId?.let { id ->
138+
state.onUpdateFilterOption(
139+
BookingsFilterOption.Customer(
140+
customerId = id,
141+
customerName = "${customer.firstName} ${customer.lastName}".trim()
142+
.ifBlank { customer.email }.orEmpty()
143+
)
144+
)
145+
}
146+
state.onClose()
147+
}
132148
}
133149
composable(BookingFilterPage.ServiceEvent.route) {
134150
TODO()

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import androidx.annotation.StringRes
55
import com.woocommerce.android.R
66
import com.woocommerce.android.model.UiString
77
import com.woocommerce.android.ui.bookings.filter.type.titleRes
8+
import com.woocommerce.android.ui.compose.DialogState
89
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingFilters
910
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption
1011

@@ -24,10 +25,11 @@ data class BookingFilterListUiState(
2425
val initialBookingFilters: BookingFilters? = null,
2526
val newBookingFilters: Set<BookingsFilterOption> = emptySet(),
2627
val currentPage: BookingFilterPage = BookingFilterPage.List,
28+
val dialogState: DialogState? = null,
2729
val onClose: () -> Unit = {},
2830
val onShowBookings: () -> Unit = {},
2931
val openPage: (BookingFilterPage) -> Unit = {},
30-
val onUpdateFilterOption: (BookingsFilterOption) -> Unit = {}
32+
val onUpdateFilterOption: (BookingsFilterOption) -> Unit = {},
3133
) {
3234

3335
val items: List<BookingFilterListItem> = availableBookingFilters().map { page ->
@@ -79,7 +81,7 @@ val BookingFilterPage.titleRes: Int
7981
BookingFilterPage.AttendanceStatus -> R.string.bookings_filter_title_attendance_status
8082
BookingFilterPage.PaymentStatus -> R.string.bookings_filter_title_payment_status
8183
BookingFilterPage.BookingType -> R.string.bookings_filter_title_type
82-
BookingFilterPage.Customer -> R.string.bookings_filter_customer_name
84+
BookingFilterPage.Customer -> R.string.bookings_filter_customer
8385
BookingFilterPage.Location -> R.string.bookings_filter_location
8486
BookingFilterPage.DateTime -> R.string.bookings_filter_title_date
8587
BookingFilterPage.ServiceEvent -> R.string.bookings_filter_title_service_event

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package com.woocommerce.android.ui.bookings.filter
22

33
import androidx.lifecycle.SavedStateHandle
44
import androidx.lifecycle.asLiveData
5+
import com.woocommerce.android.R
6+
import com.woocommerce.android.model.UiString
57
import com.woocommerce.android.ui.bookings.filter.data.BookingFilterRepository
8+
import com.woocommerce.android.ui.compose.DialogState
69
import com.woocommerce.android.viewmodel.MultiLiveEvent
710
import com.woocommerce.android.viewmodel.ScopedViewModel
811
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -25,7 +28,7 @@ class BookingFilterListViewModel @Inject constructor(
2528
onClose = ::onClose,
2629
onShowBookings = ::onShowBookings,
2730
openPage = ::onOpenPage,
28-
onUpdateFilterOption = ::onUpdateFilterOption,
31+
onUpdateFilterOption = ::onUpdateFilterOption
2932
)
3033
)
3134
val uiState = _uiState.asLiveData()
@@ -66,8 +69,25 @@ class BookingFilterListViewModel @Inject constructor(
6669
current.copy(currentPage = BookingFilterPage.List)
6770
}
6871
} else {
69-
// TODO Verify unsaved changes and close
70-
triggerEvent(MultiLiveEvent.Event.Exit)
72+
if (hasUnsavedChanges()) {
73+
_uiState.update { current ->
74+
current.copy(
75+
dialogState = DialogState(
76+
message = R.string.discard_message,
77+
positiveButton = DialogState.DialogButton(
78+
text = UiString.UiStringRes(R.string.discard),
79+
onClick = ::onDiscardChanges
80+
),
81+
negativeButton = DialogState.DialogButton(
82+
text = UiString.UiStringRes(R.string.keep_changes),
83+
onClick = ::onDismissUnsavedChangesDialog
84+
),
85+
)
86+
)
87+
}
88+
} else {
89+
triggerEvent(MultiLiveEvent.Event.Exit)
90+
}
7191
}
7292
}
7393

@@ -77,6 +97,22 @@ class BookingFilterListViewModel @Inject constructor(
7797
}
7898
triggerEvent(MultiLiveEvent.Event.Exit)
7999
}
100+
101+
private fun onDismissUnsavedChangesDialog() {
102+
_uiState.update { current -> current.copy(dialogState = null) }
103+
}
104+
105+
private fun onDiscardChanges() {
106+
// Hide dialog and exit without saving
107+
_uiState.update { current -> current.copy(dialogState = null) }
108+
triggerEvent(MultiLiveEvent.Event.Exit)
109+
}
110+
111+
private fun hasUnsavedChanges(): Boolean {
112+
val initial = _uiState.value.initialBookingFilters ?: BookingFilters()
113+
val updated = _uiState.value.updatedBookingFilters
114+
return updated != initial
115+
}
80116
}
81117

82118
private val BookingFilterListUiState.updatedBookingFilters: BookingFilters
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.woocommerce.android.ui.bookings.filter.customer
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
5+
import com.woocommerce.android.model.Order
6+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListSelectionScreen
7+
8+
@Composable
9+
fun BookingCustomerFilterPage(
10+
onCustomerSelected: (Order.Customer) -> Unit,
11+
) {
12+
val viewModel = hiltViewModel { factory: BookingCustomerFilterViewModel.Factory ->
13+
factory.create(onCustomerSelected)
14+
}
15+
16+
CustomerListSelectionScreen(
17+
viewModel = viewModel,
18+
handleInsets = false,
19+
showToolbar = false
20+
)
21+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.woocommerce.android.ui.bookings.filter.customer
2+
3+
import androidx.lifecycle.SavedStateHandle
4+
import com.woocommerce.android.analytics.AnalyticsTrackerWrapper
5+
import com.woocommerce.android.model.Order
6+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListGetSupportedSearchModes
7+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListIsAdvancedSearchSupported
8+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListRepository
9+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListSelectionViewModel
10+
import com.woocommerce.android.ui.orders.creation.customerlist.CustomerListViewModelMapper
11+
import com.woocommerce.android.util.StringUtils
12+
import dagger.assisted.Assisted
13+
import dagger.assisted.AssistedFactory
14+
import dagger.assisted.AssistedInject
15+
import dagger.hilt.android.lifecycle.HiltViewModel
16+
17+
@Suppress("LongParameterList")
18+
@HiltViewModel(assistedFactory = BookingCustomerFilterViewModel.Factory::class)
19+
class BookingCustomerFilterViewModel @AssistedInject constructor(
20+
savedStateHandle: SavedStateHandle,
21+
repository: CustomerListRepository,
22+
mapper: CustomerListViewModelMapper,
23+
isAdvancedSearchSupported: CustomerListIsAdvancedSearchSupported,
24+
getSupportedSearchModes: CustomerListGetSupportedSearchModes,
25+
analyticsTracker: AnalyticsTrackerWrapper,
26+
stringUtils: StringUtils,
27+
@Assisted private val onCustomerSelected: (Order.Customer) -> Unit
28+
) : CustomerListSelectionViewModel(
29+
savedStateHandle,
30+
repository,
31+
mapper,
32+
isAdvancedSearchSupported,
33+
getSupportedSearchModes,
34+
analyticsTracker,
35+
stringUtils
36+
) {
37+
override fun exitWithCustomer(customer: Order.Customer) {
38+
this.onCustomerSelected.invoke(customer)
39+
}
40+
41+
@AssistedFactory
42+
interface Factory {
43+
fun create(onCustomerSelected: (Order.Customer) -> Unit): BookingCustomerFilterViewModel
44+
}
45+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/creation/customerlist/CustomerListDialogFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class CustomerListDialogFragment : DialogFragment() {
4141
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
4242
setContent {
4343
WooThemeWithBackground {
44-
OrderCustomerListScreen(viewModel = viewModel, handleInsets = true)
44+
CustomerListSelectionScreen(viewModel = viewModel, handleInsets = true)
4545
}
4646
}
4747
}
Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,17 @@ import org.wordpress.android.fluxc.model.customer.WCCustomerModel
3535
* bug https://issuetracker.google.com/issues/411868840 the insets are re-applied when the keyboard is shown.
3636
*/
3737
@Composable
38-
fun OrderCustomerListScreen(
38+
fun CustomerListSelectionScreen(
3939
viewModel: CustomerListSelectionViewModel,
40-
handleInsets: Boolean
40+
handleInsets: Boolean,
41+
showToolbar: Boolean = true
4142
) {
4243
val state by viewModel.viewState.observeAsState()
4344
state?.let {
44-
OrderCustomerListScreen(
45+
CustomerListSelectionScreen(
4546
state = it,
4647
handleInsets = handleInsets,
48+
showToolbar = showToolbar,
4749
onNavigateBack = viewModel::onNavigateBack,
4850
onAddCustomerClicked = viewModel::onAddCustomerClicked,
4951
onCustomerSelected = viewModel::onCustomerSelected,
@@ -55,9 +57,10 @@ fun OrderCustomerListScreen(
5557
}
5658

5759
@Composable
58-
fun OrderCustomerListScreen(
60+
private fun CustomerListSelectionScreen(
5961
state: CustomerListViewState,
6062
handleInsets: Boolean,
63+
showToolbar: Boolean,
6164
onNavigateBack: () -> Unit,
6265
onAddCustomerClicked: () -> Unit,
6366
onCustomerSelected: (WCCustomerModel) -> Unit,
@@ -68,12 +71,14 @@ fun OrderCustomerListScreen(
6871
) {
6972
Scaffold(
7073
topBar = {
71-
Toolbar(
72-
title = stringResource(id = R.string.order_creation_add_customer),
73-
navigationIcon = Icons.AutoMirrored.Filled.ArrowBack,
74-
onNavigationButtonClick = onNavigateBack,
75-
windowInsets = if (handleInsets) AppBarDefaults.topAppBarWindowInsets else WindowInsets(0),
76-
)
74+
if (showToolbar) {
75+
Toolbar(
76+
title = stringResource(id = R.string.order_creation_add_customer),
77+
navigationIcon = Icons.AutoMirrored.Filled.ArrowBack,
78+
onNavigationButtonClick = onNavigateBack,
79+
windowInsets = if (handleInsets) AppBarDefaults.topAppBarWindowInsets else WindowInsets(0),
80+
)
81+
}
7782
},
7883
floatingActionButton = {
7984
if (state.showFab) CustomerListAddCustomerButton(onAddCustomerClicked)
@@ -111,7 +116,7 @@ private fun CustomerListAddCustomerButton(onClick: () -> Unit) {
111116
@Composable
112117
fun OrderCustomerListScreenPreview() {
113118
WooThemeWithBackground {
114-
OrderCustomerListScreen(
119+
CustomerListSelectionScreen(
115120
state = CustomerListViewState(
116121
searchHint = R.string.order_creation_customer_search_hint,
117122
searchQuery = "",
@@ -171,6 +176,7 @@ fun OrderCustomerListScreenPreview() {
171176
),
172177
),
173178
handleInsets = false,
179+
showToolbar = true,
174180
onNavigateBack = {},
175181
onAddCustomerClicked = {},
176182
onCustomerSelected = {},

0 commit comments

Comments
 (0)