Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import kotlinx.coroutines.launch
@Composable
fun ShipmentDetails(
scaffoldState: BottomSheetScaffoldState,
shippableItems: ShippableItemsUI,
shippingLines: List<ShippingLineSummaryUI>,
markOrderComplete: Boolean,
onMarkOrderCompleteChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
Expand Down Expand Up @@ -98,18 +100,26 @@ fun ShipmentDetails(
}
}
if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) {
ShipmentDetailsLandscape(modifier = modifier)
ShipmentDetailsLandscape(
shippableItems = shippableItems,
shippingLines = shippingLines,
modifier = modifier
)
} else {
ShipmentDetailsPortrait(
modifier = modifier,
shippableItems = shippableItems,
shippingLines = shippingLines,
markOrderComplete = markOrderComplete,
onMarkOrderCompleteChange = onMarkOrderCompleteChange
onMarkOrderCompleteChange = onMarkOrderCompleteChange,
modifier = modifier
)
}
}

@Composable
private fun ShipmentDetailsPortrait(
shippableItems: ShippableItemsUI,
shippingLines: List<ShippingLineSummaryUI>,
markOrderComplete: Boolean,
onMarkOrderCompleteChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
Expand All @@ -126,9 +136,9 @@ private fun ShipmentDetailsPortrait(
OrderDetailsSection(
shipFrom = getShipFrom(),
shipTo = getShipTo(),
totalItems = 5,
totalItemsCost = "$120.99",
shippingLines = getShippingLines(3)
totalItems = shippableItems.shippableItems.size,
totalItemsCost = shippableItems.formattedTotalPrice,
shippingLines = shippingLines
)
Divider(modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.major_100)))
ShipmentCostSection(
Expand All @@ -147,6 +157,8 @@ private fun ShipmentDetailsPortrait(

@Composable
private fun ShipmentDetailsLandscape(
shippableItems: ShippableItemsUI,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier,
) {
Column(modifier) {
Expand All @@ -169,9 +181,9 @@ private fun ShipmentDetailsLandscape(
.fillMaxWidth()
) {
OrderDetailsSectionLandscape(
totalItems = 5,
totalItemsCost = "$120.99",
shippingLines = getShippingLines(3),
totalItems = shippableItems.shippableItems.size,
totalItemsCost = shippableItems.formattedTotalPrice,
shippingLines = shippingLines,
modifier = Modifier.weight(1f)
)
VerticalDivider(modifier = Modifier.padding(top = dimensionResource(R.dimen.major_100)))
Expand Down Expand Up @@ -214,7 +226,7 @@ private fun OrderDetailsSection(
shipTo: Address,
totalItems: Int,
totalItemsCost: String,
shippingLines: List<ShippingLineSummary>,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier,
) {
Column(modifier.fillMaxWidth()) {
Expand All @@ -241,7 +253,7 @@ private fun OrderDetailsSection(
private fun OrderDetailsSectionLandscape(
totalItems: Int,
totalItemsCost: String,
shippingLines: List<ShippingLineSummary>,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier,
) {
Column(modifier.fillMaxWidth()) {
Expand All @@ -266,7 +278,14 @@ private fun OrderDetailsSectionLandscape(
fun ShipmentDetailsLandscapePreview() {
WooThemeWithBackground {
Surface {
ShipmentDetailsLandscape()
ShipmentDetailsLandscape(
shippableItems = ShippableItemsUI(
shippableItems = generateItems(6),
formattedTotalWeight = "8.5kg",
formattedTotalPrice = "$92.78"
),
shippingLines = getShippingLines()
)
}
}
}
Expand All @@ -275,7 +294,7 @@ fun ShipmentDetailsLandscapePreview() {
private fun TotalCard(
totalItems: Int,
totalItemsCost: String,
shippingLines: List<ShippingLineSummary>,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier
) {
Column(modifier) {
Expand Down Expand Up @@ -314,7 +333,7 @@ private fun ItemsCostPreview() {

@Composable
private fun ShippingLines(
shippingLines: List<ShippingLineSummary>,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier
) {
Column(modifier) {
Expand Down Expand Up @@ -445,16 +464,16 @@ private fun ShipmentCostSectionPreview() {
}
}

private fun getShippingLines(number: Int = 3) = List(number) { i ->
ShippingLineSummary(
fun getShippingLines(number: Int = 3) = List(number) { i ->
ShippingLineSummaryUI(
title = "Shipping $i",
amount = "$12.99"
)
}

fun Address.toShippingFromString() = this.getEnvelopeAddress().replace("\n", " ")

data class ShippingLineSummary(
data class ShippingLineSummaryUI(
val title: String,
val amount: String
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ fun WooShippingLabelCreationScreen(viewModel: WooShippingLabelCreationViewModel)
WooShippingLabelCreationScreen(
onSelectPackageClick = viewModel::onSelectPackageClicked,
onPurchaseShippingLabel = viewModel::onPurchaseShippingLabel,
shippableItems = viewState.shippableItems
shippableItems = viewState.shippableItems,
shippingLines = viewState.shippingLines
)
}
}
Expand All @@ -70,6 +71,7 @@ fun WooShippingLabelCreationScreen(viewModel: WooShippingLabelCreationViewModel)
@Composable
fun WooShippingLabelCreationScreen(
shippableItems: ShippableItemsUI,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier,
onSelectPackageClick: () -> Unit,
onPurchaseShippingLabel: () -> Unit
Expand All @@ -80,7 +82,8 @@ fun WooShippingLabelCreationScreen(
shippableItems = shippableItems,
modifier = modifier,
onSelectPackageClick = onSelectPackageClick,
scaffoldState = scaffoldState
scaffoldState = scaffoldState,
shippingLines = shippingLines
)
val isDarkTheme = isSystemInDarkTheme()
val isCollapsed = scaffoldState.bottomSheetState.isCollapsed
Expand Down Expand Up @@ -115,6 +118,7 @@ fun WooShippingLabelCreationScreen(
@Composable
private fun LabelCreationScreenWithBottomSheet(
shippableItems: ShippableItemsUI,
shippingLines: List<ShippingLineSummaryUI>,
modifier: Modifier = Modifier,
onSelectPackageClick: () -> Unit,
scaffoldState: BottomSheetScaffoldState
Expand All @@ -123,10 +127,12 @@ private fun LabelCreationScreenWithBottomSheet(
sheetContent = {
val markOrderComplete = remember { mutableStateOf(false) }
ShipmentDetails(
modifier = Modifier.padding(bottom = 74.dp),
shippableItems = shippableItems,
shippingLines = shippingLines,
scaffoldState = scaffoldState,
markOrderComplete = markOrderComplete.value,
onMarkOrderCompleteChange = { markOrderComplete.value = it }
onMarkOrderCompleteChange = { markOrderComplete.value = it },
modifier = Modifier.padding(bottom = 74.dp),
)
},
sheetPeekHeight = 132.dp,
Expand Down Expand Up @@ -204,6 +210,7 @@ private fun WooShippingLabelCreationScreenPreview() {
formattedTotalWeight = "8.5kg",
formattedTotalPrice = "$92.78"
),
shippingLines = getShippingLines(),
modifier = Modifier.fillMaxSize(),
onSelectPackageClick = {},
onPurchaseShippingLabel = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.woocommerce.android.ui.orders.wooshippinglabels
import androidx.lifecycle.SavedStateHandle
import com.woocommerce.android.extensions.formatToString
import com.woocommerce.android.extensions.sumByFloat
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.orders.details.OrderDetailRepository
import com.woocommerce.android.ui.orders.wooshippinglabels.models.ShippableItemModel
import com.woocommerce.android.ui.orders.wooshippinglabels.models.StoreOptionsModel
Expand All @@ -12,7 +13,6 @@ import com.woocommerce.android.viewmodel.ScopedViewModel
import com.woocommerce.android.viewmodel.navArgs
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import javax.inject.Inject

Expand All @@ -37,22 +37,22 @@ class WooShippingLabelCreationViewModel @Inject constructor(
init {
launch {
orderDetailRepository.getOrderById(navArgs.orderId)?.let { order ->
shippableItems.value = getShippableItems(order)
}
}
val items = getShippableItems(order)
shippableItems.value = items

launch {
shippableItems.filter { it.isNotEmpty() }.collect { items ->
val shippableItems = items.map { item -> item.toUIModel(currencyFormatter, storeOptions) }
val shippableItemsUI = items.map { item -> item.toUIModel(currencyFormatter, storeOptions) }
val formattedTotalPrice = getTotalPrice(items)
val formattedTotalWeight = getTotalWeight(items)

val shippingLineSummary = getShippingLinesSummary(order)

viewState.value = WooShippingViewState.DataState(
shippableItems = ShippableItemsUI(
shippableItems = shippableItems,
shippableItems = shippableItemsUI,
formattedTotalWeight = formattedTotalWeight,
formattedTotalPrice = formattedTotalPrice
)
),
shippingLines = shippingLineSummary
)
}
}
Expand All @@ -71,6 +71,15 @@ class WooShippingLabelCreationViewModel @Inject constructor(
return "${totalWeight.formatToString()} ${storeOptions.weightUnit}"
}

private fun getShippingLinesSummary(order: Order): List<ShippingLineSummaryUI> {
return order.shippingLines.map {
ShippingLineSummaryUI(
title = it.methodTitle,
amount = currencyFormatter.formatCurrency(it.total, order.currency)
)
}
}

fun onSelectPackageClicked() {
triggerEvent(StartPackageSelection)
}
Expand All @@ -85,7 +94,8 @@ class WooShippingLabelCreationViewModel @Inject constructor(
sealed class WooShippingViewState {
data object Loading : WooShippingViewState()
data class DataState(
val shippableItems: ShippableItemsUI
val shippableItems: ShippableItemsUI,
val shippingLines: List<ShippingLineSummaryUI>
) : WooShippingViewState()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.woocommerce.android.ui.orders.wooshippinglabels

import androidx.lifecycle.SavedStateHandle
import com.woocommerce.android.model.Order
import com.woocommerce.android.ui.orders.OrderTestUtils
import com.woocommerce.android.ui.orders.details.OrderDetailRepository
import com.woocommerce.android.ui.orders.wooshippinglabels.WooShippingLabelCreationViewModel.WooShippingViewState
import com.woocommerce.android.ui.orders.wooshippinglabels.models.ShippableItemModel
import com.woocommerce.android.util.CurrencyFormatter
import com.woocommerce.android.viewmodel.BaseUnitTest
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import java.math.BigDecimal
import kotlin.test.assertEquals

@OptIn(ExperimentalCoroutinesApi::class)
class WooShippingLabelCreationViewModelTest : BaseUnitTest() {
private val orderId = 1L
private val defaultShippableItems = List(3) {
ShippableItemModel(
itemId = it.toLong(),
productId = it.toLong(),
title = "Product $it",
price = BigDecimal(it),
quantity = it.toFloat(),
weight = it.toFloat(),
currency = "USD",
imageUrl = "https://example.com/image.jpg",
width = it.toFloat(),
height = it.toFloat(),
length = it.toFloat()
)
}
private val defaultShippingLines = List(3) {
Order.ShippingLine(
methodTitle = "Shipping Line $it",
total = BigDecimal(it),
methodId = it.toString(),
itemId = it.toLong(),
totalTax = BigDecimal.ZERO,
)
}
private val orderDetailRepository: OrderDetailRepository = mock()
private val getShippableItems: GetShippableItems = mock()
private val currencyFormatter: CurrencyFormatter = mock {
on { formatCurrency(any<BigDecimal>(), any(), any()) } doAnswer {
val amount = it.getArgument(0) as BigDecimal
"$ ${amount.toPlainString()}"
}
}
private val savedState: SavedStateHandle =
WooShippingLabelCreationFragmentArgs(orderId = orderId).toSavedStateHandle()

private lateinit var sut: WooShippingLabelCreationViewModel

fun createViewModel() {
sut = WooShippingLabelCreationViewModel(
orderDetailRepository = orderDetailRepository,
getShippableItems = getShippableItems,
currencyFormatter = currencyFormatter,
savedState = savedState
)
}

@Test
fun `when the order NO contains shipping lines, then NO shipping lines summary is displayed`() = testBlocking {
val order = OrderTestUtils.generateTestOrder(orderId = orderId).copy(
shippingLines = emptyList()
)
whenever(orderDetailRepository.getOrderById(any())) doReturn order
whenever(getShippableItems(any())) doReturn defaultShippableItems

createViewModel()

val currentViewState = sut.viewState.value
assert(currentViewState is WooShippingViewState.DataState)
val dataState = currentViewState as WooShippingViewState.DataState
assert(dataState.shippingLines.isEmpty())
}

@Test
fun `when the order contains shipping lines, then shipping lines summary is displayed`() = testBlocking {
val order = OrderTestUtils.generateTestOrder(orderId = orderId).copy(
shippingLines = defaultShippingLines
)
whenever(orderDetailRepository.getOrderById(any())) doReturn order
whenever(getShippableItems(any())) doReturn defaultShippableItems

createViewModel()

val currentViewState = sut.viewState.value
assert(currentViewState is WooShippingViewState.DataState)
val dataState = currentViewState as WooShippingViewState.DataState
assert(dataState.shippingLines.isNotEmpty())
assertEquals(dataState.shippingLines.size, defaultShippingLines.size)
}
}