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 @@ -39,7 +39,7 @@ sealed class ChildToParentEvent {
data object OrderSuccessfullyPaidByCard : ChildToParentEvent()
data object ExitPosClicked : ChildToParentEvent()
data object SimpleProductExplanationMenuItemClicked : ChildToParentEvent()
data object BarcodeInfoMenuItemClicked : ChildToParentEvent()
data object SetupBarcodeScannerClicked : ChildToParentEvent()
data object CouponsValidationFailed : ChildToParentEvent()
data object RemoveCouponsClicked : ChildToParentEvent()
data class CouponsRemoved(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class WooPosHomeViewModel @Inject constructor(
)
}

ChildToParentEvent.BarcodeInfoMenuItemClicked -> {
ChildToParentEvent.SetupBarcodeScannerClicked -> {
_state.value = _state.value.copy(
dialogState = DialogState.ScanningSetupDialog
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkHorizontally
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
Expand All @@ -35,11 +36,14 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.DeleteOutline
import androidx.compose.material.icons.outlined.AddShoppingCart
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.DocumentScanner
import androidx.compose.material.icons.outlined.Inventory2
import androidx.compose.material.icons.outlined.LocalOffer
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
Expand All @@ -55,14 +59,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
Expand Down Expand Up @@ -140,7 +142,9 @@ private fun WooPosCartScreen(
start.linkTo(parent.start)
end.linkTo(parent.end)
height = Dimension.fillToConstraints
}
},
onBarcodeSetupClicked = { onUIEvent(WooPosCartUIEvent.BarcodeSetupClicked) },
isPosSettingsFeatureEnabled = state.isPosSettingsFeatureEnabled
)
}

Expand Down Expand Up @@ -192,28 +196,106 @@ private fun WooPosCartScreen(
}

@Composable
fun CartBodyEmpty(modifier: Modifier = Modifier) {
fun CartBodyEmpty(
modifier: Modifier = Modifier,
onBarcodeSetupClicked: () -> Unit = {},
isPosSettingsFeatureEnabled: Boolean,
) {
Column(
modifier = modifier
.padding(WooPosSpacing.Medium.value.toAdaptivePadding()),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
imageVector = ImageVector.vectorResource(R.drawable.ic_woo_pos_empty_cart),
contentDescription = stringResource(R.string.woopos_cart_empty_content_description),
modifier = Modifier.size(88.dp),
colorFilter = ColorFilter.tint(
color = MaterialTheme.colorScheme.surface.copy(alpha = 0.4F),
blendMode = BlendMode.SrcAtop,
EmptyStateSection(
icon = Icons.Outlined.AddShoppingCart,
iconContentDescription = stringResource(R.string.woopos_cart_empty_content_description),
text = stringResource(R.string.woopos_cart_empty_subtitle)
)

if (isPosSettingsFeatureEnabled) {
Spacer(modifier = Modifier.height(WooPosSpacing.Large.value.toAdaptivePadding()))

EmptyCartOrDivider()

Spacer(modifier = Modifier.height(WooPosSpacing.Large.value.toAdaptivePadding()))

EmptyStateSection(
icon = Icons.Outlined.DocumentScanner,
text = stringResource(R.string.woopos_cart_empty_scan_products),
action = onBarcodeSetupClicked
)
}
}
}

@Composable
private fun EmptyStateSection(
icon: ImageVector,
iconContentDescription: String? = null,
text: String,
action: (() -> Unit)? = null
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Icon(
imageVector = icon,
contentDescription = iconContentDescription,
modifier = Modifier
.size(66.dp)
.let { modifier ->
iconContentDescription?.let {
modifier.semantics { contentDescription = it }
} ?: modifier
},
tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.5F)
)

Spacer(
modifier = Modifier.height(WooPosSpacing.Medium.value.toAdaptivePadding())
)

WooPosText(
text = text,
style = WooPosTypography.BodyMedium,
color = WooPosTheme.colors.onSurfaceVariantHighest,
textAlign = TextAlign.Center
)

action?.let {
WooPosText(
text = stringResource(R.string.woopos_cart_empty_setup_scanner),
style = WooPosTypography.BodyMedium,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier
.clickable { it() }
.padding(WooPosSpacing.Medium.value.toAdaptivePadding())
)
}
}
}

@Composable
private fun EmptyCartOrDivider() {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
HorizontalDivider(
modifier = Modifier.weight(1f),
color = WooPosTheme.colors.onSurfaceVariantLowest.copy(alpha = 0.15f)
)
Spacer(modifier = Modifier.height(WooPosSpacing.XLarge.value.toAdaptivePadding()))
WooPosText(
text = stringResource(R.string.woopos_cart_empty_subtitle),
style = WooPosTypography.BodyLarge,
text = stringResource(R.string.woopos_cart_empty_or),
style = WooPosTypography.BodySmall,
fontWeight = FontWeight.Bold,
color = WooPosTheme.colors.onSurfaceVariantLowest,
textAlign = TextAlign.Center
modifier = Modifier.padding(horizontal = WooPosSpacing.Medium.value.toAdaptivePadding())
)
HorizontalDivider(
modifier = Modifier.weight(1f),
color = WooPosTheme.colors.onSurfaceVariantLowest.copy(alpha = 0.15f)
)
}
}
Expand Down Expand Up @@ -485,7 +567,8 @@ private fun ClearCartButton(
DropdownMenu(
expanded = dropdownExpanded,
onDismissRequest = { dropdownExpanded = false },
modifier = Modifier.defaultMinSize(minWidth = 200.dp)
modifier = Modifier
.defaultMinSize(minWidth = 200.dp)
.background(color = MaterialTheme.colorScheme.surfaceContainerLowest),
) {
DropdownMenuItem(
Expand Down Expand Up @@ -587,7 +670,7 @@ private fun ProductItem(
Column(
modifier = Modifier
.weight(1f)
.padding(end = WooPosSpacing.Medium.value.toAdaptivePadding(),)
.padding(end = WooPosSpacing.Medium.value.toAdaptivePadding())
.padding(vertical = WooPosSpacing.Medium.value.toAdaptivePadding())
) {
WooPosText(
Expand Down Expand Up @@ -1069,7 +1152,8 @@ fun WooPosCartScreenEmptyPreview(modifier: Modifier = Modifier) {
),
body = WooPosCartState.Body.Empty,
areItemsRemovable = false,
checkoutButtonState = WooPosCartState.CheckoutButtonState.Invisible
checkoutButtonState = WooPosCartState.CheckoutButtonState.Invisible,
isPosSettingsFeatureEnabled = true
)
) {}
}
Expand All @@ -1095,7 +1179,7 @@ fun WooPosCartScreenErrorLoadingPreview(modifier: Modifier = Modifier) {
),
WooPosCartItemViewState.Loading(
itemNumber = 2,
name = "ADAXS1313XDVZX"
name = "nADAXS1313XDVZX"
),
WooPosCartItemViewState.Error(
itemNumber = 3,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ data class WooPosCartState(
val body: Body = Body.Empty,
val areItemsRemovable: Boolean = true,
val checkoutButtonState: CheckoutButtonState = CheckoutButtonState.Enabled,
val isPosSettingsFeatureEnabled: Boolean = false,
) : Parcelable {
@Parcelize
sealed class Body : Parcelable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ sealed class WooPosCartUIEvent {
data class OnBarcodeEvent(
val result: BarcodeInputDetector.BarcodeResult
) : WooPosCartUIEvent()
data object BarcodeSetupClicked : WooPosCartUIEvent()
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.woocommerce.android.ui.woopos.common.data.searchbyidentifier.WooPosSe
import com.woocommerce.android.ui.woopos.common.data.searchbyidentifier.WooPosSearchByIdentifierResult
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper
import com.woocommerce.android.ui.woopos.common.util.WooPosSoundHelper
import com.woocommerce.android.ui.woopos.featureflags.WooPosPosSettingsEnabled
import com.woocommerce.android.ui.woopos.home.ChildToParentEvent
import com.woocommerce.android.ui.woopos.home.ChildToParentEvent.CouponsRemoved
import com.woocommerce.android.ui.woopos.home.ChildToParentEvent.OnNewTransactionStarted
Expand Down Expand Up @@ -68,11 +69,12 @@ class WooPosCartViewModel @Inject constructor(
private val wooPosLogWrapper: WooPosLogWrapper,
private val soundHelper: WooPosSoundHelper,
private val barcodeEventTracker: WooPosBarcodeEventTracker,
private val posSettingsEnabled: WooPosPosSettingsEnabled,
savedState: SavedStateHandle,
) : ViewModel() {
private val _state = savedState.getStateFlow(
scope = viewModelScope,
initialValue = WooPosCartState(),
initialValue = WooPosCartState(isPosSettingsFeatureEnabled = posSettingsEnabled()),
key = "cartViewState"
)

Expand Down Expand Up @@ -131,6 +133,10 @@ class WooPosCartViewModel @Inject constructor(
is WooPosCartUIEvent.OnBarcodeEvent -> {
onBarcodeEvent(event.result)
}

WooPosCartUIEvent.BarcodeSetupClicked -> {
sendEventToParent(ChildToParentEvent.SetupBarcodeScannerClicked)
}
}
}

Expand Down Expand Up @@ -346,7 +352,7 @@ class WooPosCartViewModel @Inject constructor(
}

private fun clearCart() {
_state.value = WooPosCartState()
_state.value = WooPosCartState(isPosSettingsFeatureEnabled = posSettingsEnabled())
}

private suspend fun handleNewTransactionIfNeeded() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class WooPosToolbarViewModel @Inject constructor(
}
R.string.woopos_barcode_scanning_title -> {
viewModelScope.launch {
childrenToParentEventSender.sendToParent(ChildToParentEvent.BarcodeInfoMenuItemClicked)
childrenToParentEventSender.sendToParent(ChildToParentEvent.SetupBarcodeScannerClicked)
}
}
R.string.woopos_product_limitations_title -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun WooPosRootHost(
is NavigationEvent.ToEmailReceipt -> onNavigationEvent(OpenEmailReceipt(it.orderId))
NavigationEvent.ExitPos -> onNavigationEvent(ExitPosClicked)
NavigationEvent.ReturnHomeFromCashWhenCardPaymentStarted -> onNavigationEvent(ReturnHomeFromCashPayment)
NavigationEvent.ToSettings -> onNavigationEvent(OpenSettings)
is NavigationEvent.ToSettings -> onNavigationEvent(OpenSettings)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ import com.woocommerce.android.ui.woopos.settings.categories.WooPosSettingsCateg
import com.woocommerce.android.ui.woopos.settings.details.WooPosSettingsDetailPaneScreen

@Composable
fun WooPosSettingsScreen(
onNavigationEvent: (WooPosNavigationEvent) -> Unit,
) {
fun WooPosSettingsScreen(onNavigationEvent: (WooPosNavigationEvent) -> Unit) {
val containerViewModel: WooPosSettingsViewModel = hiltViewModel()
val state by containerViewModel.state.collectAsState()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.woocommerce.android.ui.woopos.settings.details.hardware
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CreditCard
import androidx.compose.material.icons.filled.QrCodeScanner
import androidx.compose.material.icons.filled.DocumentScanner
import androidx.compose.ui.graphics.vector.ImageVector
import com.woocommerce.android.R

Expand All @@ -18,7 +18,7 @@ data class WooPosHardwareSettingsState(
HardwareSettingsItem(
titleRes = R.string.woopos_settings_hardware_barcode_scanners,
subtitleRes = R.string.woopos_settings_hardware_barcode_scanners_subtitle,
icon = Icons.Default.QrCodeScanner
icon = Icons.Default.DocumentScanner,
),
HardwareSettingsItem(
titleRes = R.string.woopos_settings_hardware_card_readers,
Expand Down
18 changes: 0 additions & 18 deletions WooCommerce/src/main/res/drawable/ic_woo_pos_empty_cart.xml

This file was deleted.

4 changes: 4 additions & 0 deletions WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4405,7 +4405,11 @@
<string name="woopos_totals_coupons_validation_failed_remove_coupons">Remove coupons</string>
<string name="woopos_cart_empty_subtitle">Tap on a product to\nadd it to the cart</string>
<string name="woopos_cart_empty_content_description">Cart is empty</string>
<string name="woopos_cart_empty_barcode_setup_label">You can also scan your products. Click here to setup barcode scanner.</string>
<string name="woopos_cart_empty_scan_products">Scan products with\na barcode scanner</string>
<string name="woopos_cart_empty_or">OR</string>
<string name="woopos_cart_empty_setup_scanner">Set up scanner</string>
<string name="woopos_products_empty_list_image_description">No products</string>

Check warning

Code scanning / Android Lint

Unused resources Warning

The resource R.string.woopos_cart_empty_barcode_setup_label appears to be unused
<string name="woopos_products_empty_list_title">No supported products found</string>
<string name="woopos_products_empty_list_message">POS currently only supports simple, variable, and virtual products – \ncreate one to get started.</string>
<string name="woopos_products_empty_list_message_two">POS currently only supports simple products</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ class WooPosHomeViewModelTest {
val events = MutableSharedFlow<ChildToParentEvent>()
whenever(childrenToParentEventReceiver.events).thenReturn(events)
val viewModel = createViewModel()
events.emit(ChildToParentEvent.BarcodeInfoMenuItemClicked)
events.emit(ChildToParentEvent.SetupBarcodeScannerClicked)
assertThat(viewModel.state.value.dialogState).isEqualTo(WooPosHomeState.DialogState.ScanningSetupDialog)

// WHEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.woocommerce.android.ui.woopos.common.data.searchbyidentifier.WooPosSe
import com.woocommerce.android.ui.woopos.common.data.searchbyidentifier.WooPosSearchByIdentifierResult
import com.woocommerce.android.ui.woopos.common.util.WooPosLogWrapper
import com.woocommerce.android.ui.woopos.common.util.WooPosSoundHelper
import com.woocommerce.android.ui.woopos.featureflags.WooPosPosSettingsEnabled
import com.woocommerce.android.ui.woopos.home.ChildToParentEvent
import com.woocommerce.android.ui.woopos.home.ParentToChildrenEvent
import com.woocommerce.android.ui.woopos.home.WooPosChildrenToParentEventSender
Expand Down Expand Up @@ -113,6 +114,9 @@ class WooPosCartViewModelTest {
private val searchByIdentifier: WooPosSearchByIdentifier = mock()
private val wooPosLogWrapper: WooPosLogWrapper = mock()
private val barcodeEventTracker: WooPosBarcodeEventTracker = mock()
private val posSettingsEnabled: WooPosPosSettingsEnabled = mock {
on { invoke() }.thenReturn(false)
}

@Test
fun `given empty cart, when product clicked in product selector, then should add product to cart`() = runTest {
Expand Down Expand Up @@ -1460,6 +1464,7 @@ class WooPosCartViewModelTest {
wooPosLogWrapper,
soundHelper,
barcodeEventTracker,
posSettingsEnabled,
savedState,
)
}
Expand Down