From 1e482a775966b7dbc5086eef2899c69d83fd70a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:05:20 +0300 Subject: [PATCH 01/12] Adds string resources for type filter --- WooCommerce/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index a6df45de5469..6dba2979f953 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -4240,6 +4240,8 @@ Date & time Service / Event Any + Service + Event Booking #%s From 13b6c07f5dbe20e2f82b53e8401c13cedf7da217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:06:55 +0300 Subject: [PATCH 02/12] Add BookingTypeFilterUiState --- .../filter/type/BookingTypeFilterUiState.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt new file mode 100644 index 000000000000..963cf81710e3 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt @@ -0,0 +1,45 @@ +package com.woocommerce.android.ui.bookings.filter.type + +import androidx.annotation.StringRes +import com.woocommerce.android.R +import com.woocommerce.android.ui.bookings.filter.BookingFilterListItem + +sealed interface BookingFilterType { + data object Any : BookingFilterType + data object Service : BookingFilterType + data object Event : BookingFilterType +} + +data class BookingTypeFilterUiState( + val selectedType: BookingFilterType = BookingFilterType.Any, + val onTypeSelected: (BookingFilterType) -> Unit = {}, +) { + val items: List = availableBookingTypes().map { type -> + BookingFilterListItem( + title = type.titleRes, + value = type.filterValue, + onClick = { onTypeSelected(type) } + ) + } + + val BookingFilterType.titleRes: Int + @StringRes get() = when (this) { + BookingFilterType.Any -> R.string.bookings_filter_default + BookingFilterType.Service -> R.string.bookings_filter_type_service + BookingFilterType.Event -> R.string.bookings_filter_type_event + } + + private fun availableBookingTypes(): List = listOf( + BookingFilterType.Any, + BookingFilterType.Service, + BookingFilterType.Event, + ) +} + +val BookingFilterType.filterValue: String? + // TODO Update this with actual endpoint values + get() = when (this) { + BookingFilterType.Service -> "service" + BookingFilterType.Event -> "event" + BookingFilterType.Any -> null + } From 0dc120fc37940ac4aab3cfc76bbdff16c4d52cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:12:15 +0300 Subject: [PATCH 03/12] Move `BookingFilterListItem` to its own file Moves the `BookingFilterListItem` data class from `BookingFilterListUiState.kt` to a new, dedicated file `BookingFilterListItem.kt` within the same package. --- .../ui/bookings/filter/BookingFilterListItem.kt | 12 ++++++++++++ .../ui/bookings/filter/BookingFilterListUiState.kt | 6 ------ 2 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListItem.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListItem.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListItem.kt new file mode 100644 index 000000000000..f4a251a8a5cf --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListItem.kt @@ -0,0 +1,12 @@ +package com.woocommerce.android.ui.bookings.filter + +import androidx.annotation.StringRes + +/** + * UI model simple filter item + */ +data class BookingFilterListItem( + @StringRes val title: Int, + val value: String? = null, + val onClick: () -> Unit = {} +) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt index 81629015432a..955ee8e9da61 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt @@ -60,12 +60,6 @@ data class BookingFilterListUiState( } } -data class BookingFilterListItem( - @StringRes val title: Int, - val value: String? = null, - val onClick: () -> Unit = {} -) - val BookingFilterPage.titleRes: Int @StringRes get() = when (this) { BookingFilterPage.TeamMember -> R.string.bookings_filter_title_team_member From 8236942cced133a9d0c097cfd0d633da7c078a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:13:00 +0300 Subject: [PATCH 04/12] Add single choice filter page This commit introduces a new Composable, `SingleChoiceFilterPage`, for displaying a list of filter options where only one can be selected at a time. --- .../bookings/filter/SingleChoiceFilterPage.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/SingleChoiceFilterPage.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/SingleChoiceFilterPage.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/SingleChoiceFilterPage.kt new file mode 100644 index 000000000000..2fe3b7893a15 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/SingleChoiceFilterPage.kt @@ -0,0 +1,74 @@ +package com.woocommerce.android.ui.bookings.filter + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.woocommerce.android.R + +@Composable +fun SingleChoiceFilterPage( + items: List, + selectedValue: String?, + modifier: Modifier = Modifier, +) { + LazyColumn(modifier = modifier) { + items(items) { item -> + SingleChoiceRow( + text = stringResource(item.title), + selected = item.value == selectedValue, + onClick = { item.onClick() } + ) + } + } +} + +@Composable +private fun SingleChoiceRow( + text: String, + selected: Boolean, + onClick: () -> Unit, +) { + Column(modifier = Modifier.fillMaxWidth()) { + Row( + modifier = Modifier + .fillMaxWidth() + .defaultMinSize(minHeight = 64.dp) + .clickable(onClick = onClick) + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = text, + style = MaterialTheme.typography.titleMedium, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f) + ) + if (selected) { + Icon( + painter = painterResource(id = R.drawable.ic_done_secondary), + contentDescription = null, + modifier = Modifier.size(26.dp), + tint = MaterialTheme.colorScheme.primary + ) + } + } + HorizontalDivider(thickness = 0.5.dp) + } +} From a249bb6333f314d6e36697b228b7cb9d1860c96c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:14:25 +0300 Subject: [PATCH 05/12] Create booking type filter page Introduces the `BookingTypeFilterPage` composable. This page utilizes the generic `SingleChoiceFilterPage` to display a list of booking type filter options. --- .../ui/bookings/filter/type/BookingTypeFilterPage.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt new file mode 100644 index 000000000000..e7aa58be79b7 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt @@ -0,0 +1,12 @@ +package com.woocommerce.android.ui.bookings.filter.type + +import androidx.compose.runtime.Composable +import com.woocommerce.android.ui.bookings.filter.SingleChoiceFilterPage + +@Composable +fun BookingTypeFilterPage(state: BookingTypeFilterUiState) { + SingleChoiceFilterPage( + items = state.items, + selectedValue = state.selectedType.filterValue, + ) +} From 640ca4d0fec3ac3a3adaf5e4a61055d623e4d7e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:07:30 +0300 Subject: [PATCH 06/12] Add dummy state for booking type filter screen --- .../ui/bookings/filter/type/BookingTypeFilterUiState.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt index 963cf81710e3..7ed16c61d085 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt @@ -43,3 +43,9 @@ val BookingFilterType.filterValue: String? BookingFilterType.Event -> "event" BookingFilterType.Any -> null } + +// TODO After refactoring navigation for the filter screens, replace this with a ViewModel-backed UI state. +val DUMMY_BOOKING_TYPE_FILTER_UI_STATE = BookingTypeFilterUiState( + selectedType = BookingFilterType.Any, + onTypeSelected = {} +) From 3b08b529782a03931f4054d2086bdf2a452de061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Wed, 29 Oct 2025 20:15:19 +0300 Subject: [PATCH 07/12] Show new booking type page in filters screens --- .../android/ui/bookings/filter/BookingFilterListScreen.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt index 23fc80bddf21..15822f5249c5 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt @@ -25,6 +25,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource import androidx.compose.ui.unit.dp import com.woocommerce.android.R +import com.woocommerce.android.ui.bookings.filter.type.BookingTypeFilterPage +import com.woocommerce.android.ui.bookings.filter.type.DUMMY_BOOKING_TYPE_FILTER_UI_STATE import com.woocommerce.android.ui.compose.component.Toolbar import com.woocommerce.android.ui.compose.component.WCColoredButton import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews @@ -85,8 +87,8 @@ fun BookingFilterListScreen(state: BookingFilterListUiState) { BookingFilterRootPage(state.items) } + BookingFilterPage.BookingType -> BookingTypeFilterPage(DUMMY_BOOKING_TYPE_FILTER_UI_STATE) BookingFilterPage.AttendanceStatus, - BookingFilterPage.BookingType, BookingFilterPage.Customer, BookingFilterPage.Location, BookingFilterPage.PaymentStatus, From d77fed5bfc4185cdf657cdca4f43047bdbe20e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Thu, 30 Oct 2025 18:15:18 +0300 Subject: [PATCH 08/12] Move BookingType filter model to FluxC --- .../filter/type/BookingTypeFilterUiState.kt | 35 ++++++++----------- .../wpcom/wc/bookings/BookingsFilterOption.kt | 6 +++- .../wpcom/wc/bookings/BookingsRestClient.kt | 2 +- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt index 7ed16c61d085..7af16b4b2954 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt @@ -3,16 +3,11 @@ package com.woocommerce.android.ui.bookings.filter.type import androidx.annotation.StringRes import com.woocommerce.android.R import com.woocommerce.android.ui.bookings.filter.BookingFilterListItem - -sealed interface BookingFilterType { - data object Any : BookingFilterType - data object Service : BookingFilterType - data object Event : BookingFilterType -} +import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption.BookingType data class BookingTypeFilterUiState( - val selectedType: BookingFilterType = BookingFilterType.Any, - val onTypeSelected: (BookingFilterType) -> Unit = {}, + val selectedType: BookingType = BookingType.Any, + val onTypeSelected: (BookingType) -> Unit = {}, ) { val items: List = availableBookingTypes().map { type -> BookingFilterListItem( @@ -22,26 +17,26 @@ data class BookingTypeFilterUiState( ) } - val BookingFilterType.titleRes: Int + val BookingType.titleRes: Int @StringRes get() = when (this) { - BookingFilterType.Any -> R.string.bookings_filter_default - BookingFilterType.Service -> R.string.bookings_filter_type_service - BookingFilterType.Event -> R.string.bookings_filter_type_event + BookingType.Any -> R.string.bookings_filter_default + BookingType.Service -> R.string.bookings_filter_type_service + BookingType.Event -> R.string.bookings_filter_type_event } - private fun availableBookingTypes(): List = listOf( - BookingFilterType.Any, - BookingFilterType.Service, - BookingFilterType.Event, + private fun availableBookingTypes(): List = listOf( + BookingType.Any, + BookingType.Service, + BookingType.Event, ) } -val BookingFilterType.filterValue: String? +val BookingType.filterValue: String? // TODO Update this with actual endpoint values get() = when (this) { - BookingFilterType.Service -> "service" - BookingFilterType.Event -> "event" - BookingFilterType.Any -> null + BookingType.Service -> "service" + BookingType.Event -> "event" + BookingType.Any -> null } // TODO After refactoring navigation for the filter screens, replace this with a ViewModel-backed UI state. diff --git a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsFilterOption.kt b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsFilterOption.kt index 02a6f8c79f8b..5e7ba72ce1f6 100644 --- a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsFilterOption.kt +++ b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsFilterOption.kt @@ -9,7 +9,11 @@ sealed interface BookingsFilterOption { object PaymentStatus : BookingsFilterOption - object BookingType : BookingsFilterOption + sealed interface BookingType : BookingsFilterOption { + object Any : BookingType + object Service : BookingType + object Event : BookingType + } data class Customer(val customerId: Long, val customerName: String) : BookingsFilterOption diff --git a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsRestClient.kt b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsRestClient.kt index d31dfcd80769..4c8659f2b819 100644 --- a/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsRestClient.kt +++ b/libs/fluxc-plugin/src/main/kotlin/org/wordpress/android/fluxc/network/rest/wpcom/wc/bookings/BookingsRestClient.kt @@ -109,7 +109,7 @@ class BookingsRestClient @Inject constructor( BookingsFilterOption.TeamMember -> TODO() BookingsFilterOption.AttendanceStatus -> TODO() BookingsFilterOption.PaymentStatus -> TODO() - BookingsFilterOption.BookingType -> TODO() + is BookingsFilterOption.BookingType -> TODO() is BookingsFilterOption.Customer -> set("customer", filter.customerId.toString()) BookingsFilterOption.Location -> TODO() From 7976b4c93a67e60b2e7dbee86df43f8c9d6e56af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Thu, 30 Oct 2025 18:16:32 +0300 Subject: [PATCH 09/12] Add BookingTypeFilterViewModel Adds a new `BookingTypeFilterViewModel` to manage the state for the booking type filter. This ViewModel handles the initial selected type and updates the UI state when a new type is selected. --- .../filter/type/BookingTypeFilterViewModel.kt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterViewModel.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterViewModel.kt new file mode 100644 index 000000000000..9b85add3aeee --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterViewModel.kt @@ -0,0 +1,40 @@ +package com.woocommerce.android.ui.bookings.filter.type + +import androidx.lifecycle.SavedStateHandle +import com.woocommerce.android.viewmodel.ScopedViewModel +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption + +@HiltViewModel(assistedFactory = BookingTypeFilterViewModel.Factory::class) +class BookingTypeFilterViewModel @AssistedInject constructor( + @Assisted private val initialType: BookingsFilterOption.BookingType, + @Assisted private val onTypeFilterChanged: (BookingsFilterOption.BookingType) -> Unit, + savedStateHandle: SavedStateHandle +) : ScopedViewModel(savedStateHandle) { + + private val _uiState = MutableStateFlow( + BookingTypeFilterUiState(selectedType = initialType, onTypeSelected = ::onTypeSelected) + ) + val uiState: StateFlow = _uiState + + private fun onTypeSelected(type: BookingsFilterOption.BookingType) { + if (_uiState.value.selectedType != type) { + _uiState.update { current -> current.copy(selectedType = type) } + } + onTypeFilterChanged(type) + } + + @AssistedFactory + interface Factory { + fun create( + initialType: BookingsFilterOption.BookingType, + onTypeFilterChanged: (BookingsFilterOption.BookingType) -> Unit + ): BookingTypeFilterViewModel + } +} From 60c9f47c4c717846098cb5626422834e342fedd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Thu, 30 Oct 2025 18:16:49 +0300 Subject: [PATCH 10/12] Add BookingTypeFilterRoute composable --- .../filter/type/BookingTypeFilterPage.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt index e7aa58be79b7..e67da15b1a82 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterPage.kt @@ -1,7 +1,24 @@ package com.woocommerce.android.ui.bookings.filter.type import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import com.woocommerce.android.ui.bookings.filter.SingleChoiceFilterPage +import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption + +@Composable +fun BookingTypeFilterRoute( + initialType: BookingsFilterOption.BookingType, + onTypeFilterChanged: (BookingsFilterOption.BookingType) -> Unit, +) { + val viewModel = hiltViewModel { factory -> + factory.create(initialType, onTypeFilterChanged) + } + + val uiState by viewModel.uiState.collectAsState() + BookingTypeFilterPage(uiState) +} @Composable fun BookingTypeFilterPage(state: BookingTypeFilterUiState) { From 59ba3a9efe5c9edbaed229c92aaeb9d7cb6586df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Thu, 30 Oct 2025 18:20:46 +0300 Subject: [PATCH 11/12] Update booking type filter selection --- .../bookings/filter/BookingFilterListScreen.kt | 7 ++++--- .../filter/BookingFilterListUiState.kt | 6 ++++++ .../filter/BookingFilterListViewModel.kt | 18 ++++++++++++++++++ .../filter/type/BookingTypeFilterUiState.kt | 6 ------ 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt index 4f54e846eaf6..ef2e5d8e5828 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt @@ -28,8 +28,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.woocommerce.android.R -import com.woocommerce.android.ui.bookings.filter.type.BookingTypeFilterPage -import com.woocommerce.android.ui.bookings.filter.type.DUMMY_BOOKING_TYPE_FILTER_UI_STATE +import com.woocommerce.android.ui.bookings.filter.type.BookingTypeFilterRoute import com.woocommerce.android.ui.compose.component.Toolbar import com.woocommerce.android.ui.compose.component.WCColoredButton import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews @@ -124,7 +123,9 @@ private fun FiltersNavHost( TODO() } composable(BookingFilterPage.BookingType.route) { - BookingTypeFilterPage(DUMMY_BOOKING_TYPE_FILTER_UI_STATE) + BookingTypeFilterRoute(initialType = state.currentBookingType) { type -> + state.onUpdateFilterOption(type) + } } composable(BookingFilterPage.Customer.route) { TODO() diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt index 27857ef78c27..4959988da92f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt @@ -25,6 +25,7 @@ data class BookingFilterListUiState( val onClose: () -> Unit = {}, val onShowBookings: () -> Unit = {}, val openPage: (BookingFilterPage) -> Unit = {}, + val onUpdateFilterOption: (BookingsFilterOption) -> Unit = {} ) { val items: List = availableBookingFilters().map { page -> @@ -35,6 +36,11 @@ data class BookingFilterListUiState( ) } + val currentBookingType: BookingsFilterOption.BookingType + get() = newBookingFilters.getOrDefault( + initialBookingFilters?.bookingType + ) ?: BookingsFilterOption.BookingType.Any + @DrawableRes val navigationIcon: Int = when (currentPage) { BookingFilterPage.List -> R.drawable.ic_gridicons_cross_24dp diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt index 086e870a7f66..014d4f8dcd6f 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingFilters +import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption import javax.inject.Inject @HiltViewModel @@ -24,6 +25,7 @@ class BookingFilterListViewModel @Inject constructor( onClose = ::onClose, onShowBookings = ::onShowBookings, openPage = ::onOpenPage, + onUpdateFilterOption = ::onUpdateFilterOption, ) ) val uiState = _uiState.asLiveData() @@ -38,6 +40,22 @@ class BookingFilterListViewModel @Inject constructor( } } + private fun onUpdateFilterOption(option: BookingsFilterOption) { + _uiState.update { current -> + val filtered = when (option) { + is BookingsFilterOption.BookingType -> current.newBookingFilters + .filterNot { it is BookingsFilterOption.BookingType } + else -> current.newBookingFilters + .filterNot { it::class == option::class } + } + current.copy( + newBookingFilters = filtered + .plus(option) + .toSet() + ) + } + } + private fun getBookingFilter() { launch { // We don't observe changes here, just get the current value once diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt index 7af16b4b2954..1a2a92dc74c0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/type/BookingTypeFilterUiState.kt @@ -38,9 +38,3 @@ val BookingType.filterValue: String? BookingType.Event -> "event" BookingType.Any -> null } - -// TODO After refactoring navigation for the filter screens, replace this with a ViewModel-backed UI state. -val DUMMY_BOOKING_TYPE_FILTER_UI_STATE = BookingTypeFilterUiState( - selectedType = BookingFilterType.Any, - onTypeSelected = {} -) From e1bee756a88c726b3afc0b1fbe53d681ae7011e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irfan=20=C3=96m=C3=BCr?= Date: Thu, 30 Oct 2025 19:25:55 +0300 Subject: [PATCH 12/12] Fix detekt error --- .../ui/bookings/filter/BookingFilterListViewModel.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt index 014d4f8dcd6f..ac649f20dd73 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListViewModel.kt @@ -43,10 +43,11 @@ class BookingFilterListViewModel @Inject constructor( private fun onUpdateFilterOption(option: BookingsFilterOption) { _uiState.update { current -> val filtered = when (option) { - is BookingsFilterOption.BookingType -> current.newBookingFilters - .filterNot { it is BookingsFilterOption.BookingType } - else -> current.newBookingFilters - .filterNot { it::class == option::class } + is BookingsFilterOption.BookingType -> { + current.newBookingFilters.filterNot { it is BookingsFilterOption.BookingType } + } + + else -> current.newBookingFilters.filterNot { it::class == option::class } } current.copy( newBookingFilters = filtered