From 182ee27375593a2f12589a719bb4165bc0fff949 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 10 Dec 2024 19:23:41 -0300 Subject: [PATCH 01/17] Update PackageData to split dimensions into length, width and height --- .../wooshippinglabels/packages/ui/UIModels.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt index 2e41ba3c487..df810f44290 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import com.woocommerce.android.R import com.woocommerce.android.extensions.isNotNullOrEmpty import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PackageType +import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @Parcelize @@ -16,6 +17,20 @@ data class PackageData( val dimensionUnit: String = "cm", val weightUnit: String = "kg" ) : Parcelable { + @IgnoredOnParcel + val length: String + @IgnoredOnParcel + val width: String + @IgnoredOnParcel + val height: String + + init { + val dimensionList = dimensions.split("x") + length = dimensionList.getOrNull(0).orEmpty().trim() + width = dimensionList.getOrNull(1).orEmpty().trim() + height = dimensionList.getOrNull(2).orEmpty().trim() + } + val descriptionResId: Int get() = when (isLetter) { true -> R.string.woo_shipping_labels_package_creation_envelope_type From b7c0454f9a87bdb4961c7c3f9d59de2e09b8572d Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 10 Dec 2024 19:23:52 -0300 Subject: [PATCH 02/17] Add unit test coverage for PackageData --- .../packages/ui/PackageDataTest.kt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt new file mode 100644 index 00000000000..8a93e3d2e51 --- /dev/null +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt @@ -0,0 +1,68 @@ +package com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui + +import kotlin.test.Test +import org.assertj.core.api.Assertions.assertThat + +class PackageDataTest { + + + @Test + fun `length, width, and height are correctly set when dimensions are properly formatted`() { + val packageData = PackageData( + name = "Test Package", + dimensions = "10 x 20 x 30", + weight = "5", + isSelected = false, + isLetter = false + ) + + assertThat(packageData.length).isEqualTo("10") + assertThat(packageData.width).isEqualTo("20") + assertThat(packageData.height).isEqualTo("30") + } + + @Test + fun `length, width, and height are empty when dimensions are not properly formatted`() { + val packageData = PackageData( + name = "Test Package", + dimensions = "10 x 20", + weight = "5", + isSelected = false, + isLetter = false + ) + + assertThat(packageData.length).isEqualTo("10") + assertThat(packageData.width).isEqualTo("20") + assertThat(packageData.height).isEmpty() + } + + @Test + fun `length, width, and height are empty when dimensions are null`() { + val packageData = PackageData( + name = "Test Package", + dimensions = "10", + weight = "5", + isSelected = false, + isLetter = false + ) + + assertThat(packageData.length).isEqualTo("10") + assertThat(packageData.width).isEmpty() + assertThat(packageData.height).isEmpty() + } + + @Test + fun `length, width, and height are empty when dimensions are empty`() { + val packageData = PackageData( + name = "Test Package", + dimensions = "", + weight = "5", + isSelected = false, + isLetter = false + ) + + assertThat(packageData.length).isEmpty() + assertThat(packageData.width).isEmpty() + assertThat(packageData.height).isEmpty() + } +} From 2458f0bc1621125c38fd9b982eb7fbe66e27c0dc Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Tue, 10 Dec 2024 20:33:28 -0300 Subject: [PATCH 03/17] Fix lint issues --- .../ui/orders/wooshippinglabels/packages/ui/UIModels.kt | 2 ++ .../ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt index df810f44290..e1540f0f197 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt @@ -19,8 +19,10 @@ data class PackageData( ) : Parcelable { @IgnoredOnParcel val length: String + @IgnoredOnParcel val width: String + @IgnoredOnParcel val height: String diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt index 8a93e3d2e51..93ae1174f65 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/PackageDataTest.kt @@ -1,11 +1,10 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui -import kotlin.test.Test import org.assertj.core.api.Assertions.assertThat +import kotlin.test.Test class PackageDataTest { - @Test fun `length, width, and height are correctly set when dimensions are properly formatted`() { val packageData = PackageData( From 86f874a55e767e53c631d25075fb8e9e87a05191 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 17:17:47 -0300 Subject: [PATCH 04/17] Define Package data state with loading and error support --- .../packages/WooShippingLabelPackageCreationViewModel.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt index 1ec4b77b0b3..bb2952733fc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt @@ -213,6 +213,15 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( val carrierPackageSection: CarrierPackageSelection = CarrierPackageSelection(emptyMap()) ) : Parcelable + sealed class PredefinedPackagesState { + data class Data( + val savedPackageSelection: SavedPackageSelection = SavedPackageSelection(emptyList()), + val carrierPackageSelection: CarrierPackageSelection = CarrierPackageSelection(emptyMap()) + ) : PredefinedPackagesState() + data object Error : PredefinedPackagesState() + data object Waiting : PredefinedPackagesState() + } + @Parcelize data class PageTab( val title: String, From 8c6a0a85f644f95261e23fdec4ccdb27d3f83906 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 17:59:11 -0300 Subject: [PATCH 05/17] Simplify Predefined Package models --- .../wooshippinglabels/packages/ui/UIModels.kt | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt index e1540f0f197..3975be27171 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/UIModels.kt @@ -116,24 +116,6 @@ sealed class Carrier( @Parcelize data class StorePredefinedPackages( - val carrierPackageSelection: CarrierPackageSelection, - val savedPackageSelection: SavedPackageSelection + val carrierPackages: Map>, + val savedPackages: List ) : Parcelable - -@Parcelize -data class CarrierPackageSelection( - val carrierPackages: Map> -) : Parcelable { - val hasSelection: Boolean - get() = carrierPackages.values.flatten().find { group -> - group.packages.find { it.isSelected } != null - } != null -} - -@Parcelize -data class SavedPackageSelection( - val packages: List -) : Parcelable { - val hasSelection: Boolean - get() = packages.find { it.isSelected } != null -} From 33745e8d59a7f78cad6795f16029ce0217c71d16 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 17:59:35 -0300 Subject: [PATCH 06/17] Overhaul WooShippingLabelPackageCreationViewModel ViewState structure --- ...ooShippingLabelPackageCreationViewModel.kt | 70 ++++++++++++------- .../FetchPredefinedPackagesFromStore.kt | 10 +-- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt index bb2952733fc..923a5e78b0b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt @@ -11,10 +11,8 @@ import com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource.W import com.woocommerce.android.ui.orders.wooshippinglabels.packages.networking.CustomPackageCreationRequestData import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageSelection import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CustomPackageCreationData import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.SavedPackageSelection import com.woocommerce.android.viewmodel.MultiLiveEvent import com.woocommerce.android.viewmodel.ResourceProvider import com.woocommerce.android.viewmodel.ScopedViewModel @@ -62,8 +60,9 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( fetchPredefinedPackages()?.let { _viewState.update { viewState -> viewState.copy( - savedPackageSelection = it.savedPackageSelection, - carrierPackageSection = it.carrierPackageSelection + predefinedPackagesState = PredefinedPackagesState.Data( + it.savedPackages, it.carrierPackages + ) ) } } @@ -72,34 +71,39 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( fun onCarrierPackageSelected(selectedPackage: PackageData, isSelected: Boolean) { _viewState.update { viewState -> - viewState.carrierPackageSection.carrierPackages - .map { updateCarrierPackagesSelection(it, selectedPackage, isSelected) } - .let { viewState.copy(carrierPackageSection = CarrierPackageSelection(it.toMap())) } + val predefinedPackages = viewState.predefinedPackagesData + predefinedPackages?.carrierPackages + ?.map { updateCarrierPackagesSelection(it, selectedPackage, isSelected) } + ?.let { viewState.copy(predefinedPackagesState = predefinedPackages.copy(carrierPackages = it.toMap())) } + ?: _viewState.value } } fun onSavedPackageSelected(selectedPackage: PackageData, isSelected: Boolean) { _viewState.update { viewState -> - viewState.savedPackageSelection.packages - .map { it.copy(isSelected = false) } - .toMutableList() - .safelyUpdate(selectedPackage, selectedPackage.copy(isSelected = isSelected)) - .let { SavedPackageSelection(it) } - .let { viewState.copy(savedPackageSelection = it) } + val predefinedPackages = viewState.predefinedPackagesData + predefinedPackages?.savedPackages + ?.map { it.copy(isSelected = false) } + ?.toMutableList() + ?.safelyUpdate(selectedPackage, selectedPackage.copy(isSelected = isSelected)) + ?.let { viewState.copy(predefinedPackagesState = predefinedPackages.copy(savedPackages = it)) } + ?: _viewState.value } } fun onAddCarrierPackageClick() { - _viewState.value.carrierPackageSection.carrierPackages - .asSequence() - .flatMap { it.value } - .flatMap { it.packages } - .find { it.isSelected } + _viewState.value.predefinedPackagesData?.carrierPackages + ?.asSequence() + ?.flatMap { it.value } + ?.flatMap { it.packages } + ?.find { it.isSelected } ?.let { triggerEvent(PackageSelected(it)) } } fun onAddSavedPackageClick() { - _viewState.value.savedPackageSelection.packages.find { it.isSelected } + _viewState.value.predefinedPackagesData + ?.savedPackages + ?.find { it.isSelected } ?.let { triggerEvent(PackageSelected(it)) } } @@ -209,17 +213,29 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( data class ViewState( val pageTabs: List = emptyList(), val customPackageCreationData: CustomPackageCreationData = CustomPackageCreationData.EMPTY, - val savedPackageSelection: SavedPackageSelection = SavedPackageSelection(emptyList()), - val carrierPackageSection: CarrierPackageSelection = CarrierPackageSelection(emptyMap()) - ) : Parcelable + val predefinedPackagesState: PredefinedPackagesState = PredefinedPackagesState.Waiting, + ) : Parcelable { + val predefinedPackagesData + get() = (predefinedPackagesState as? PredefinedPackagesState.Data) + } - sealed class PredefinedPackagesState { - data class Data( - val savedPackageSelection: SavedPackageSelection = SavedPackageSelection(emptyList()), - val carrierPackageSelection: CarrierPackageSelection = CarrierPackageSelection(emptyMap()) - ) : PredefinedPackagesState() + @Parcelize + sealed class PredefinedPackagesState : Parcelable { data object Error : PredefinedPackagesState() data object Waiting : PredefinedPackagesState() + data class Data( + val savedPackages: List = emptyList(), + val carrierPackages: Map> = emptyMap() + ) : PredefinedPackagesState() { + val hasCarrierSelection: Boolean + get() = carrierPackages.values.flatten().find { group -> + group.packages.find { it.isSelected } != null + } != null + + + val hasSavedSelection: Boolean + get() = savedPackages.find { it.isSelected } != null + } } @Parcelize diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt index d61b44ef4cd..339731d3fdf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt @@ -3,9 +3,7 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageSelection import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.SavedPackageSelection import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.StorePredefinedPackages import javax.inject.Inject @@ -21,12 +19,8 @@ class FetchPredefinedPackagesFromStore @Inject constructor( ?: return null return StorePredefinedPackages( - savedPackageSelection = storePackages - .filterSavedData() - .let { SavedPackageSelection(it) }, - carrierPackageSelection = storePackages - .filterCarrierData() - .let { CarrierPackageSelection(it) } + savedPackages = storePackages.filterSavedData(), + carrierPackages = storePackages.filterCarrierData() ) } From 8f20d5478b9cb87c892e33a011a0cc8b00a975b6 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 17:59:55 -0300 Subject: [PATCH 07/17] Update Saved and Carrier Package screens to follow new ViewState structure --- .../packages/ui/WooShippingCarrierPackageScreen.kt | 4 ++-- .../packages/ui/WooShippingSavedPackageScreen.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt index 8aa8d6ae64f..f297806aecc 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt @@ -47,8 +47,8 @@ import kotlinx.coroutines.launch fun WooShippingCarrierPackageScreen(viewModel: WooShippingLabelPackageCreationViewModel) { val viewState by viewModel.viewState.observeAsState() WooShippingCarrierPackageScreen( - carrierPackages = viewState?.carrierPackageSection?.carrierPackages ?: emptyMap(), - isAddPackageEnabled = viewState?.carrierPackageSection?.hasSelection ?: false, + carrierPackages = viewState?.predefinedPackagesData?.carrierPackages ?: emptyMap(), + isAddPackageEnabled = viewState?.predefinedPackagesData?.hasCarrierSelection ?: false, onPackageSelected = viewModel::onCarrierPackageSelected, onAddPackageClick = viewModel::onAddCarrierPackageClick ) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt index 06a854e50ea..7d2974d4f5b 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt @@ -24,8 +24,8 @@ import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.W fun WooShippingSavedPackageScreen(viewModel: WooShippingLabelPackageCreationViewModel) { val viewState = viewModel.viewState.observeAsState() WooShippingSavedPackageScreen( - savedPackages = viewState.value?.savedPackageSelection?.packages.orEmpty(), - isAddPackageEnabled = viewState.value?.savedPackageSelection?.hasSelection ?: false, + savedPackages = viewState.value?.predefinedPackagesData?.savedPackages.orEmpty(), + isAddPackageEnabled = viewState.value?.predefinedPackagesData?.hasSavedSelection ?: false, onAddPackageClick = viewModel::onAddSavedPackageClick, onSavedPackageSelected = viewModel::onSavedPackageSelected From 2d2197ab68b3620c76296d5aa69026a9aba46f5a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 18:16:07 -0300 Subject: [PATCH 08/17] Update FetchPredefinedPackagesFromStore to return PredefinedPackagesState values --- .../WooShippingLabelPackageCreationViewModel.kt | 13 ++++--------- .../datasource/FetchPredefinedPackagesFromStore.kt | 8 ++++---- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt index 923a5e78b0b..15d309bc243 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt @@ -57,15 +57,10 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( init { launch { - fetchPredefinedPackages()?.let { - _viewState.update { viewState -> - viewState.copy( - predefinedPackagesState = PredefinedPackagesState.Data( - it.savedPackages, it.carrierPackages - ) - ) - } - } + fetchPredefinedPackages() + .let { _viewState.value.copy(predefinedPackagesState = it) } + .let { _viewState.update { it } } + } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt index 339731d3fdf..25927bf1ddf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStore.kt @@ -1,24 +1,24 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource import com.woocommerce.android.tools.SelectedSite +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PredefinedPackagesState import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.StorePredefinedPackages import javax.inject.Inject class FetchPredefinedPackagesFromStore @Inject constructor( private val selectedSite: SelectedSite, private val packageRepository: WooShippingLabelPackageRepository ) { - suspend operator fun invoke(): StorePredefinedPackages? { + suspend operator fun invoke(): PredefinedPackagesState { val storePackages = selectedSite.getOrNull() ?.let { packageRepository.fetchAllStorePackages(it) } ?.takeIf { it.isError.not() } ?.model - ?: return null + ?: return PredefinedPackagesState.Error - return StorePredefinedPackages( + return PredefinedPackagesState.Data( savedPackages = storePackages.filterSavedData(), carrierPackages = storePackages.filterCarrierData() ) From 8cca04b5c6b6a15a1a61ad961d1dc3a23aaa3a25 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 18:24:16 -0300 Subject: [PATCH 09/17] Fix build errors from unit tests --- ...ippingLabelPackageCreationViewModelTest.kt | 52 ++++++++++--------- .../FetchPredefinedPackagesFromStoreTest.kt | 11 ++-- 2 files changed, 33 insertions(+), 30 deletions(-) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt index 84edfe96e91..4f2337fddf6 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt @@ -5,17 +5,15 @@ import com.woocommerce.android.R import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PackageSelected import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PackageType +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PredefinedPackagesState import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.ShowPackageTypeDialog import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.ViewState import com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource.FetchPredefinedPackagesFromStore import com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource.WooShippingLabelPackageRepository import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageSelection import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CustomPackageCreationData import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.SavedPackageSelection -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.StorePredefinedPackages import com.woocommerce.android.viewmodel.BaseUnitTest import com.woocommerce.android.viewmodel.MultiLiveEvent import com.woocommerce.android.viewmodel.ResourceProvider @@ -187,11 +185,9 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { isLetter = true ) whenever(fetchPredefinedPackages()).thenReturn( - StorePredefinedPackages( - carrierPackageSelection = CarrierPackageSelection(emptyMap()), - savedPackageSelection = SavedPackageSelection( - listOf(package1, package2) - ) + PredefinedPackagesState.Data( + carrierPackages = emptyMap(), + savedPackages = listOf(package1, package2) ) ) @@ -205,7 +201,7 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { sut.viewState.observeForever { lastViewState = it } sut.onSavedPackageSelected(package1, true) - val selectedPackages = lastViewState?.savedPackageSelection?.packages?.filter { it.isSelected } + val selectedPackages = lastViewState?.predefinedPackagesData?.savedPackages?.filter { it.isSelected } assertThat(selectedPackages).isNotNull assertThat(selectedPackages).size().isEqualTo(1) assertThat(selectedPackages?.first()).isEqualTo(package1.copy(isSelected = true)) @@ -238,11 +234,9 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { ) ) whenever(fetchPredefinedPackages()).thenReturn( - StorePredefinedPackages( - carrierPackageSelection = CarrierPackageSelection(carrierPackages), - savedPackageSelection = SavedPackageSelection( - emptyList() - ) + PredefinedPackagesState.Data( + carrierPackages = carrierPackages, + savedPackages = emptyList() ) ) @@ -256,9 +250,14 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { sut.viewState.observeForever { lastViewState = it } sut.onCarrierPackageSelected(package1, true) - val selectedPackages = lastViewState?.carrierPackageSection?.carrierPackages?.values?.flatten()?.flatMap { - it.packages - }?.filter { it.isSelected } + val selectedPackages = lastViewState + ?.predefinedPackagesData + ?.carrierPackages + ?.values + ?.flatten() + ?.flatMap { it.packages } + ?.filter { it.isSelected } + assertThat(selectedPackages).isNotNull assertThat(selectedPackages).size().isEqualTo(1) assertThat(selectedPackages?.first()).isEqualTo(package1.copy(isSelected = true)) @@ -313,11 +312,9 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { ) ) whenever(fetchPredefinedPackages()).thenReturn( - StorePredefinedPackages( - carrierPackageSelection = CarrierPackageSelection(carrierPackages), - savedPackageSelection = SavedPackageSelection( - emptyList() - ) + PredefinedPackagesState.Data( + carrierPackages = carrierPackages, + savedPackages = emptyList() ) ) @@ -332,9 +329,14 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { sut.onCarrierPackageSelected(package1, true) sut.onCarrierPackageSelected(package2, true) - val selectedPackages = lastViewState?.carrierPackageSection?.carrierPackages?.values?.flatten()?.flatMap { - it.packages - }?.filter { it.isSelected } + val selectedPackages = lastViewState + ?.predefinedPackagesData + ?.carrierPackages + ?.values + ?.flatten() + ?.flatMap { it.packages } + ?.filter { it.isSelected } + assertThat(selectedPackages).isNotNull assertThat(selectedPackages).size().isEqualTo(1) assertThat(selectedPackages?.first()).isEqualTo(package2.copy(isSelected = true)) diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt index 105767adf6f..1172c32b804 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt @@ -1,6 +1,7 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.packages.datasource import com.woocommerce.android.tools.SelectedSite +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PredefinedPackagesState import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData @@ -33,9 +34,9 @@ class FetchPredefinedPackagesFromStoreTest : BaseUnitTest() { whenever(selectedSite.getOrNull()).thenReturn(site) whenever(packageRepository.fetchAllStorePackages(site)).thenReturn(WooResult(storePackages)) - val result = fetchPredefinedPackagesFromStore()!! + val result = fetchPredefinedPackagesFromStore() as PredefinedPackagesState.Data - assertThat(result.savedPackageSelection.packages).containsExactly( + assertThat(result.savedPackages).containsExactly( PackageData( name = "Saved Package 1", dimensions = "dimensions", @@ -51,7 +52,7 @@ class FetchPredefinedPackagesFromStoreTest : BaseUnitTest() { isLetter = false ) ) - assertThat(result.carrierPackageSelection.carrierPackages[Carrier.USPS]).containsExactly( + assertThat(result.carrierPackages[Carrier.USPS]).containsExactly( CarrierPackageGroup( groupName = "Group 1", packages = listOf( @@ -68,7 +69,7 @@ class FetchPredefinedPackagesFromStoreTest : BaseUnitTest() { } @Test - fun `invoke should return null StorePredefinedPackages when fetchAllStorePackages returns error`() = testBlocking { + fun `invoke should return Error StorePredefinedPackages when fetchAllStorePackages returns error`() = testBlocking { val error = WooError(WooErrorType.GENERIC_ERROR, BaseRequest.GenericErrorType.UNKNOWN) val site = SiteModel().apply { id = 1 } whenever(selectedSite.getOrNull()).thenReturn(site) @@ -76,7 +77,7 @@ class FetchPredefinedPackagesFromStoreTest : BaseUnitTest() { val result = fetchPredefinedPackagesFromStore() - assertThat(result).isNull() + assertThat(result).isEqualTo(PredefinedPackagesState.Error) } @Test From 2d97ee1edb45ef1bb9c82c223a37eb42f5601e20 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 18:32:17 -0300 Subject: [PATCH 10/17] Fix unit test errors --- .../packages/WooShippingLabelPackageCreationViewModel.kt | 8 +++++--- .../WooShippingLabelPackageCreationViewModelTest.kt | 3 +++ .../datasource/FetchPredefinedPackagesFromStoreTest.kt | 4 ++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt index 15d309bc243..95d074c2dd6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt @@ -57,9 +57,11 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( init { launch { - fetchPredefinedPackages() - .let { _viewState.value.copy(predefinedPackagesState = it) } - .let { _viewState.update { it } } + fetchPredefinedPackages().let { response -> + _viewState.update { viewState -> + viewState.copy(predefinedPackagesState = response) + } + } } } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt index 4f2337fddf6..89f4f2073e2 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModelTest.kt @@ -18,6 +18,7 @@ import com.woocommerce.android.viewmodel.BaseUnitTest import com.woocommerce.android.viewmodel.MultiLiveEvent import com.woocommerce.android.viewmodel.ResourceProvider import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceUntilIdle import org.assertj.core.api.Assertions.assertThat import org.junit.Before import org.junit.Test @@ -325,9 +326,11 @@ class WooShippingLabelPackageCreationViewModelTest : BaseUnitTest() { fetchPredefinedPackages, packageRepository ) + sut.viewState.observeForever { lastViewState = it } sut.onCarrierPackageSelected(package1, true) sut.onCarrierPackageSelected(package2, true) + advanceUntilIdle() val selectedPackages = lastViewState ?.predefinedPackagesData diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt index 1172c32b804..3ed7d7910ca 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/datasource/FetchPredefinedPackagesFromStoreTest.kt @@ -81,12 +81,12 @@ class FetchPredefinedPackagesFromStoreTest : BaseUnitTest() { } @Test - fun `invoke should return null StorePredefinedPackages when site is not available`() = testBlocking { + fun `invoke should return Error StorePredefinedPackages when site is not available`() = testBlocking { whenever(selectedSite.getOrNull()).thenReturn(null) val result = fetchPredefinedPackagesFromStore() - assertThat(result).isNull() + assertThat(result).isEqualTo(PredefinedPackagesState.Error) } private fun generatePackagesData() = StorePackagesDAO( From 5c3d86cd305382b977169bc7aad1c78529aeda2f Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 18:36:30 -0300 Subject: [PATCH 11/17] Fix lint issues --- .../packages/WooShippingLabelPackageCreationViewModel.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt index 95d074c2dd6..158ae224dab 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationViewModel.kt @@ -62,7 +62,6 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( viewState.copy(predefinedPackagesState = response) } } - } } @@ -71,8 +70,9 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( val predefinedPackages = viewState.predefinedPackagesData predefinedPackages?.carrierPackages ?.map { updateCarrierPackagesSelection(it, selectedPackage, isSelected) } - ?.let { viewState.copy(predefinedPackagesState = predefinedPackages.copy(carrierPackages = it.toMap())) } - ?: _viewState.value + ?.let { + viewState.copy(predefinedPackagesState = predefinedPackages.copy(carrierPackages = it.toMap())) + } ?: _viewState.value } } @@ -229,7 +229,6 @@ class WooShippingLabelPackageCreationViewModel @Inject constructor( group.packages.find { it.isSelected } != null } != null - val hasSavedSelection: Boolean get() = savedPackages.find { it.isSelected } != null } From 8901f7bff4f7061caf242fae88c3e77c1cebe3d5 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:01:15 -0300 Subject: [PATCH 12/17] Define WooShippingPackageListItemSkeleton --- ...geListItem.kt => PackageItemComponents.kt} | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) rename WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/{WooShippingPackageListItem.kt => PackageItemComponents.kt} (53%) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/WooShippingPackageListItem.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/PackageItemComponents.kt similarity index 53% rename from WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/WooShippingPackageListItem.kt rename to WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/PackageItemComponents.kt index c6ff4c75a4a..4eda4257339 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/WooShippingPackageListItem.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/components/PackageItemComponents.kt @@ -4,7 +4,10 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material.Divider import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -13,13 +16,16 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.woocommerce.android.R +import com.woocommerce.android.ui.compose.animations.SkeletonView import com.woocommerce.android.ui.compose.component.SelectionCheck +import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData @Composable -fun WooSavedPackageListItem( +fun WooShippingPackageListItem( modifier: Modifier, packageData: PackageData, onPackageSelected: (PackageData, Boolean) -> Unit @@ -60,3 +66,68 @@ fun WooSavedPackageListItem( Divider() } } + +@Composable +fun WooShippingPackageListItemSkeleton( + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .padding(top = 8.dp) + .fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + SkeletonView( + modifier = Modifier.size(24.dp) + ) + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + SkeletonView( + modifier = Modifier + .height(16.dp) + .fillMaxWidth(0.5f) + ) + SkeletonView( + modifier = Modifier + .height(20.dp) + .fillMaxWidth(0.7f) + ) + SkeletonView( + modifier = Modifier + .height(16.dp) + .fillMaxWidth(0.6f) + ) + } + } + Divider() + } +} + +@Preview +@Composable +fun WooSavedPackageListItemPreview() { + WooThemeWithBackground { + WooShippingPackageListItem( + modifier = Modifier, + packageData = PackageData( + name = "Small Flat Rate Box", + dimensions = "5 x 5 x 5", + weight = "1.5", + isLetter = false, + isSelected = false + ), + onPackageSelected = { _, _ -> } + ) + } +} + +@Preview +@Composable +fun WooSavedPackageListItemSkeletonPreview() { + WooThemeWithBackground { + WooShippingPackageListItemSkeleton() + } +} From 5b000d3f179e0caa4915cf3d975d90a300ccacfd Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:01:59 -0300 Subject: [PATCH 13/17] Refactor WooShippingSavedPackageScreen to account for Error and Loading scenarios --- .../ui/WooShippingSavedPackageScreen.kt | 54 +++++++++++++++++-- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt index 7d2974d4f5b..678652397b0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt @@ -18,13 +18,15 @@ import androidx.compose.ui.unit.dp import com.woocommerce.android.R import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooSavedPackageListItem +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PredefinedPackagesState +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooShippingPackageListItem +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooShippingPackageListItemSkeleton @Composable fun WooShippingSavedPackageScreen(viewModel: WooShippingLabelPackageCreationViewModel) { val viewState = viewModel.viewState.observeAsState() WooShippingSavedPackageScreen( - savedPackages = viewState.value?.predefinedPackagesData?.savedPackages.orEmpty(), + packageState = viewState.value?.predefinedPackagesState ?: PredefinedPackagesState.Waiting, isAddPackageEnabled = viewState.value?.predefinedPackagesData?.hasSavedSelection ?: false, onAddPackageClick = viewModel::onAddSavedPackageClick, onSavedPackageSelected = viewModel::onSavedPackageSelected @@ -34,6 +36,50 @@ fun WooShippingSavedPackageScreen(viewModel: WooShippingLabelPackageCreationView @Composable fun WooShippingSavedPackageScreen( + modifier: Modifier = Modifier, + packageState: PredefinedPackagesState, + isAddPackageEnabled: Boolean, + onAddPackageClick: () -> Unit, + onSavedPackageSelected: (PackageData, Boolean) -> Unit +) { + when (packageState) { + is PredefinedPackagesState.Data -> { + WooShippingSavedPackageContent( + modifier = modifier, + savedPackages = packageState.savedPackages, + isAddPackageEnabled = isAddPackageEnabled, + onAddPackageClick = onAddPackageClick, + onSavedPackageSelected = onSavedPackageSelected + ) + } + + is PredefinedPackagesState.Error -> { + Column( + modifier = modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()) + ) { + Text("Error") + } + } + is PredefinedPackagesState.Waiting -> { + Column( + modifier = modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()) + ) { + WooShippingPackageListItemSkeleton() + WooShippingPackageListItemSkeleton() + WooShippingPackageListItemSkeleton() + } + } + } +} + +@Composable +fun WooShippingSavedPackageContent( modifier: Modifier = Modifier, savedPackages: List, isAddPackageEnabled: Boolean, @@ -51,7 +97,7 @@ fun WooShippingSavedPackageScreen( .verticalScroll(rememberScrollState()) ) { savedPackages.forEach { packageData -> - WooSavedPackageListItem( + WooShippingPackageListItem( modifier, packageData, onSavedPackageSelected @@ -77,7 +123,7 @@ fun WooShippingSavedPackageScreen( @Composable fun WooShippingSavedPackageScreenPreview() { WooThemeWithBackground { - WooShippingSavedPackageScreen( + WooShippingSavedPackageContent( savedPackages = listOf( PackageData( name = "Small Flat Rate Box", From 7bc5bdc55e8ca67a7a2a336142cf8b57d3f8bb3a Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:03:30 -0300 Subject: [PATCH 14/17] Fix Package screens import errors --- .../WooShippingLabelPackageCreationScreen.kt | 3 ++- .../packages/ui/WooShippingCarrierPackageScreen.kt | 4 ++-- .../packages/ui/WooShippingSavedPackageScreen.kt | 13 +++++++++++++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt index 82808a44459..fbc49df6df0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt @@ -28,6 +28,7 @@ import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingL import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingCarrierPackageScreen import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingCustomPackageCreationScreen +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingSavedPackageContent import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingSavedPackageScreen @Composable @@ -128,7 +129,7 @@ fun WooShippingLabelsPackageCreationScreenPreview() { ) }, createSavedPackageScreen = { - WooShippingSavedPackageScreen( + WooShippingSavedPackageContent( savedPackages = listOf( PackageData( name = "Small Flat Rate Box", diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt index f297806aecc..d0716d43590 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt @@ -40,7 +40,7 @@ import androidx.compose.ui.unit.dp import com.woocommerce.android.R import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel -import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooSavedPackageListItem +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooShippingPackageListItem import kotlinx.coroutines.launch @Composable @@ -195,7 +195,7 @@ private fun PackageListSection( ) Divider() packages.forEach { packageData -> - WooSavedPackageListItem( + WooShippingPackageListItem( modifier = Modifier.padding(start = 16.dp), packageData = packageData, onPackageSelected = onPackageSelected diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt index 678652397b0..282eb773d80 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt @@ -153,3 +153,16 @@ fun WooShippingSavedPackageScreenPreview() { ) } } + +@Preview +@Composable +fun WooShippingSavedPackageScreenLoadingPreview() { + WooThemeWithBackground { + WooShippingSavedPackageScreen( + packageState = PredefinedPackagesState.Waiting, + isAddPackageEnabled = false, + onAddPackageClick = {}, + onSavedPackageSelected = { _, _ -> } + ) + } +} From 00fba724f698bbdf1d278ddb91fde077ce141bc5 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:08:36 -0300 Subject: [PATCH 15/17] Add proper error string resource --- .../ui/WooShippingSavedPackageScreen.kt | 17 ++++++++++++++++- WooCommerce/src/main/res/values/strings.xml | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt index 282eb773d80..2ad5dc063fd 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.material.Divider import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -55,12 +56,13 @@ fun WooShippingSavedPackageScreen( is PredefinedPackagesState.Error -> { Column( + horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier .fillMaxSize() .padding(16.dp) .verticalScroll(rememberScrollState()) ) { - Text("Error") + Text(text = stringResource(id = R.string.woo_shipping_labels_package_creation_error)) } } is PredefinedPackagesState.Waiting -> { @@ -166,3 +168,16 @@ fun WooShippingSavedPackageScreenLoadingPreview() { ) } } + +@Preview +@Composable +fun WooShippingSavedPackageScreenErrorPreview() { + WooThemeWithBackground { + WooShippingSavedPackageScreen( + packageState = PredefinedPackagesState.Error, + isAddPackageEnabled = false, + onAddPackageClick = {}, + onSavedPackageSelected = { _, _ -> } + ) + } +} diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index ceffd7785af..93688d53d77 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -4381,6 +4381,7 @@ Package Name Save this as a new package template Add Package + Failed to load the package data Box Envelope Hmm, we can\'t find a WordPress.com account connected to this email address. From b42387dd465963b016884d1a6468cb62a75a059e Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:28:13 -0300 Subject: [PATCH 16/17] Update WooShippingLabelPackageCreationScreen preview data --- .../WooShippingLabelPackageCreationScreen.kt | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt index fbc49df6df0..480e0e7f436 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/WooShippingLabelPackageCreationScreen.kt @@ -25,7 +25,10 @@ import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingL import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PageType.CARRIER import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PageType.CUSTOM import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PageType.SAVED +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.Carrier +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.CarrierPackageGroup import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.PackageData +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingCarrierPackageContent import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingCarrierPackageScreen import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingCustomPackageCreationScreen import com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui.WooShippingSavedPackageContent @@ -158,7 +161,74 @@ fun WooShippingLabelsPackageCreationScreenPreview() { onSavedPackageSelected = { _, _ -> } ) }, - createCarrierPackageScreen = { } + createCarrierPackageScreen = { + WooShippingCarrierPackageContent( + carrierPackages = mapOf( + Carrier.DHL to listOf( + CarrierPackageGroup( + groupName = "Group 1", + packages = listOf( + PackageData( + name = "Package 1 - Carrier 1", + dimensions = "10 x 10 x 10", + weight = "10", + isSelected = false, + isLetter = false + ), + PackageData( + name = "Package 2 - Carrier 1", + dimensions = "20 x 20 x 20", + weight = "20", + isSelected = false, + isLetter = false + ) + ) + ), + CarrierPackageGroup( + groupName = "Group 2", + packages = listOf( + PackageData( + name = "Package 3 - Carrier 1", + dimensions = "30 x 30 x 30", + weight = "30", + isSelected = false, + isLetter = false + ), + PackageData( + name = "Package 4 - Carrier 1", + dimensions = "40 x 40 x 40", + weight = "40", + isSelected = false, + isLetter = false + ) + ) + ) + ), + Carrier.USPS to listOf( + CarrierPackageGroup( + groupName = "Group 2", + packages = listOf( + PackageData( + name = "Package 1 - Carrier 2", + dimensions = "10 x 10 x 10", + weight = "10", + isSelected = false, + isLetter = false + ), + PackageData( + name = "Package 2 Carrier - 2", + dimensions = "20 x 20 x 20", + weight = "20", + isSelected = false, + isLetter = false + ) + ) + ) + ) + ), + onPackageSelected = { _, _ -> } + ) + } ) } } From 16a8e5b3ed1282b045c9b7ca9671c566969cfee9 Mon Sep 17 00:00:00 2001 From: ThomazFB Date: Wed, 11 Dec 2024 19:28:40 -0300 Subject: [PATCH 17/17] Add Loading and Error support to WooShippingCarrierPackageScreen --- .../ui/WooShippingCarrierPackageScreen.kt | 58 +++++++++++++++++-- .../ui/WooShippingSavedPackageScreen.kt | 1 + 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt index d0716d43590..d39f544cbbf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingCarrierPackageScreen.kt @@ -1,7 +1,6 @@ package com.woocommerce.android.ui.orders.wooshippinglabels.packages.ui import androidx.annotation.DrawableRes -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -15,7 +14,9 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button import androidx.compose.material.Divider import androidx.compose.material.Icon @@ -40,23 +41,70 @@ import androidx.compose.ui.unit.dp import com.woocommerce.android.R import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.WooShippingLabelPackageCreationViewModel.PredefinedPackagesState import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooShippingPackageListItem +import com.woocommerce.android.ui.orders.wooshippinglabels.packages.components.WooShippingPackageListItemSkeleton import kotlinx.coroutines.launch @Composable fun WooShippingCarrierPackageScreen(viewModel: WooShippingLabelPackageCreationViewModel) { val viewState by viewModel.viewState.observeAsState() WooShippingCarrierPackageScreen( - carrierPackages = viewState?.predefinedPackagesData?.carrierPackages ?: emptyMap(), + packageState = viewState?.predefinedPackagesState ?: PredefinedPackagesState.Waiting, isAddPackageEnabled = viewState?.predefinedPackagesData?.hasCarrierSelection ?: false, onPackageSelected = viewModel::onCarrierPackageSelected, onAddPackageClick = viewModel::onAddCarrierPackageClick ) } -@OptIn(ExperimentalFoundationApi::class) @Composable fun WooShippingCarrierPackageScreen( + modifier: Modifier = Modifier, + packageState: PredefinedPackagesState, + onPackageSelected: (PackageData, Boolean) -> Unit, + isAddPackageEnabled: Boolean = false, + onAddPackageClick: () -> Unit = {} +) { + when (packageState) { + is PredefinedPackagesState.Data -> { + WooShippingCarrierPackageContent( + modifier = modifier, + carrierPackages = packageState.carrierPackages, + onPackageSelected = onPackageSelected, + isAddPackageEnabled = isAddPackageEnabled, + onAddPackageClick = onAddPackageClick + ) + } + + is PredefinedPackagesState.Error -> { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()) + ) { + Text(text = stringResource(id = R.string.woo_shipping_labels_package_creation_error)) + } + } + + is PredefinedPackagesState.Waiting -> { + Column( + modifier = modifier + .fillMaxSize() + .padding(16.dp) + .verticalScroll(rememberScrollState()) + ) { + WooShippingPackageListItemSkeleton() + WooShippingPackageListItemSkeleton() + WooShippingPackageListItemSkeleton() + } + } + } +} + +@Composable +fun WooShippingCarrierPackageContent( modifier: Modifier = Modifier, carrierPackages: Map>, onPackageSelected: (PackageData, Boolean) -> Unit, @@ -94,7 +142,6 @@ fun WooShippingCarrierPackageScreen( } } -@OptIn(ExperimentalFoundationApi::class) @Composable private fun CarrierTabRow( modifier: Modifier, @@ -137,7 +184,6 @@ private fun CarrierTabRow( } } -@OptIn(ExperimentalFoundationApi::class) @Composable private fun PackageListPager( modifier: Modifier, @@ -223,7 +269,7 @@ private fun CarrierLogo( @Composable fun WooShippingCarrierPackageScreenPreview() { WooThemeWithBackground { - WooShippingCarrierPackageScreen( + WooShippingCarrierPackageContent( carrierPackages = mapOf( Carrier.DHL to listOf( CarrierPackageGroup( diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt index 2ad5dc063fd..121a78d248d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/packages/ui/WooShippingSavedPackageScreen.kt @@ -65,6 +65,7 @@ fun WooShippingSavedPackageScreen( Text(text = stringResource(id = R.string.woo_shipping_labels_package_creation_error)) } } + is PredefinedPackagesState.Waiting -> { Column( modifier = modifier