Skip to content

Commit e80e478

Browse files
authored
Merge pull request #13817 from woocommerce/fix/refactor-shipping-label-notices
[Shipping Labels Revamp] Refactor shipping label notices
2 parents 50aa394 + 29e7e66 commit e80e478

13 files changed

+512
-578
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/ShipmentDetails.kt

+4-212
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ package com.woocommerce.android.ui.orders.wooshippinglabels
33
import android.content.res.Configuration
44
import android.os.Parcelable
55
import androidx.compose.animation.AnimatedVisibility
6-
import androidx.compose.animation.core.tween
7-
import androidx.compose.animation.fadeIn
8-
import androidx.compose.animation.fadeOut
9-
import androidx.compose.animation.scaleIn
10-
import androidx.compose.animation.scaleOut
116
import androidx.compose.foundation.background
127
import androidx.compose.foundation.clickable
138
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -24,9 +19,7 @@ import androidx.compose.foundation.layout.padding
2419
import androidx.compose.foundation.layout.size
2520
import androidx.compose.foundation.layout.sizeIn
2621
import androidx.compose.foundation.layout.width
27-
import androidx.compose.foundation.layout.widthIn
2822
import androidx.compose.foundation.rememberScrollState
29-
import androidx.compose.foundation.shape.RoundedCornerShape
3023
import androidx.compose.foundation.verticalScroll
3124
import androidx.compose.material.BottomSheetScaffoldState
3225
import androidx.compose.material.Divider
@@ -36,13 +29,8 @@ import androidx.compose.material.ModalBottomSheetState
3629
import androidx.compose.material.ModalBottomSheetValue
3730
import androidx.compose.material.Surface
3831
import androidx.compose.material.Text
39-
import androidx.compose.material.icons.Icons
40-
import androidx.compose.material.icons.outlined.CheckCircleOutline
41-
import androidx.compose.material.icons.outlined.Close
42-
import androidx.compose.material.icons.outlined.Info
4332
import androidx.compose.material.rememberModalBottomSheetState
4433
import androidx.compose.runtime.Composable
45-
import androidx.compose.runtime.LaunchedEffect
4634
import androidx.compose.runtime.remember
4735
import androidx.compose.ui.Alignment
4836
import androidx.compose.ui.Modifier
@@ -60,16 +48,16 @@ import com.woocommerce.android.R
6048
import com.woocommerce.android.extensions.appendWithIfNotEmpty
6149
import com.woocommerce.android.ui.compose.animations.SkeletonView
6250
import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground
63-
import com.woocommerce.android.ui.orders.wooshippinglabels.address.AddressNotification
6451
import com.woocommerce.android.ui.orders.wooshippinglabels.address.AddressSectionLandscape
6552
import com.woocommerce.android.ui.orders.wooshippinglabels.address.AddressSectionPortrait
6653
import com.woocommerce.android.ui.orders.wooshippinglabels.address.AddressStatus
6754
import com.woocommerce.android.ui.orders.wooshippinglabels.address.getShipFrom
6855
import com.woocommerce.android.ui.orders.wooshippinglabels.address.getShipTo
56+
import com.woocommerce.android.ui.orders.wooshippinglabels.components.NoticeBanner
57+
import com.woocommerce.android.ui.orders.wooshippinglabels.components.NoticeBannerUiState
6958
import com.woocommerce.android.ui.orders.wooshippinglabels.models.DestinationShippingAddress
7059
import com.woocommerce.android.ui.orders.wooshippinglabels.models.OriginShippingAddress
7160
import com.woocommerce.android.util.StringUtils
72-
import kotlinx.coroutines.delay
7361
import kotlinx.parcelize.Parcelize
7462

7563
@Composable
@@ -80,17 +68,14 @@ fun ShipmentDetails(
8068
shippingLines: List<ShippingLineSummaryUI>,
8169
shippingAddresses: WooShippingAddresses,
8270
shippingRateSummary: ShippingRateSummaryUI?,
83-
addressNotification: AddressNotification?,
84-
itnNotification: ItnMissingNotification? = null,
8571
modifier: Modifier = Modifier,
72+
noticeBannerUiState: NoticeBannerUiState? = null,
8673
isShipmentDetailsExpanded: Boolean = false,
8774
onShipmentDetailsExpandedChange: (Boolean) -> Boolean,
8875
onEditDestinationAddress: (DestinationShippingAddress) -> Unit,
89-
onEditOriginAddress: (OriginShippingAddress) -> Unit,
9076
destinationStatus: AddressStatus,
9177
markOrderComplete: Boolean = false,
9278
onMarkOrderCompleteChange: (Boolean) -> Unit = {},
93-
onDismissAddressNotification: () -> Unit = {},
9479
handlerModifier: Modifier = Modifier,
9580
isReadOnly: Boolean = false
9681
) {
@@ -128,23 +113,7 @@ fun ShipmentDetails(
128113
.padding(top = dimensionResource(R.dimen.minor_100) * LocalConfiguration.current.fontScale)
129114
)
130115

131-
ShippingAddressNotification(
132-
addressNotification = addressNotification,
133-
onDismiss = onDismissAddressNotification,
134-
onAction = {
135-
addressNotification?.let {
136-
when {
137-
it.isSuccess.not() && it.isDestinationNotification -> {
138-
onEditDestinationAddress(shippingAddresses.shipTo)
139-
}
140-
it.isSuccess.not() && it.isDestinationNotification.not() -> {
141-
onEditOriginAddress(shippingAddresses.shipFrom)
142-
}
143-
}
144-
}
145-
}
146-
)
147-
ItnMissingNotification(itnNotification)
116+
NoticeBanner(noticeBannerUiState)
148117

149118
Spacer(
150119
modifier = Modifier.size(
@@ -559,178 +528,6 @@ private fun ShipmentCostRow(
559528
}
560529
}
561530

562-
@Composable
563-
private fun ItnMissingNotification(
564-
itnNotification: ItnMissingNotification?,
565-
modifier: Modifier = Modifier
566-
) {
567-
AnimatedVisibility(
568-
visible = itnNotification != null,
569-
enter = fadeIn(
570-
animationSpec = tween(
571-
durationMillis = 180
572-
)
573-
) + scaleIn(
574-
animationSpec = tween(
575-
durationMillis = 180
576-
)
577-
),
578-
exit = fadeOut(
579-
animationSpec = tween(
580-
durationMillis = 90
581-
)
582-
) + scaleOut(
583-
animationSpec = tween(
584-
durationMillis = 90
585-
)
586-
587-
)
588-
) {
589-
if (itnNotification == null) return@AnimatedVisibility
590-
591-
val rowModifier = when (LocalConfiguration.current.orientation) {
592-
Configuration.ORIENTATION_LANDSCAPE -> {
593-
modifier.widthIn(max = 600.dp).fillMaxWidth()
594-
}
595-
else -> {
596-
modifier.fillMaxWidth()
597-
}
598-
}
599-
600-
Row(
601-
verticalAlignment = Alignment.CenterVertically,
602-
modifier = rowModifier
603-
.padding(dimensionResource(R.dimen.major_100))
604-
.background(
605-
color = colorResource(R.color.woo_red_5),
606-
shape = RoundedCornerShape(dimensionResource(R.dimen.corner_radius_large))
607-
)
608-
.padding(vertical = 8.dp, horizontal = 16.dp),
609-
) {
610-
Icon(
611-
imageVector = Icons.Outlined.Info,
612-
tint = MaterialTheme.colors.error,
613-
contentDescription = null
614-
)
615-
Spacer(Modifier.size(dimensionResource(R.dimen.minor_50)))
616-
Text(
617-
text = itnNotification.errorMessage,
618-
style = MaterialTheme.typography.body2,
619-
color = MaterialTheme.colors.error,
620-
modifier = Modifier.weight(1f)
621-
)
622-
Icon(
623-
imageVector = Icons.Outlined.Close,
624-
tint = MaterialTheme.colors.error,
625-
contentDescription = null,
626-
modifier = Modifier.clickable {
627-
itnNotification.onErrorDismissed()
628-
}
629-
)
630-
}
631-
}
632-
}
633-
634-
@Composable
635-
private fun ShippingAddressNotification(
636-
addressNotification: AddressNotification?,
637-
modifier: Modifier = Modifier,
638-
onAction: () -> Unit = {},
639-
onDismiss: () -> Unit = {}
640-
) {
641-
AnimatedVisibility(
642-
visible = addressNotification != null && addressNotification.isExpired().not(),
643-
enter = fadeIn(
644-
animationSpec = tween(
645-
durationMillis = 180
646-
)
647-
) + scaleIn(
648-
animationSpec = tween(
649-
durationMillis = 180
650-
)
651-
),
652-
exit = fadeOut(
653-
animationSpec = tween(
654-
durationMillis = 90
655-
)
656-
) + scaleOut(
657-
animationSpec = tween(
658-
durationMillis = 90
659-
)
660-
661-
)
662-
) {
663-
if (addressNotification != null && addressNotification.isExpired().not()) {
664-
if (addressNotification.expireAfter != null) {
665-
LaunchedEffect(addressNotification) {
666-
delay(addressNotification.expireAfter)
667-
onDismiss()
668-
}
669-
}
670-
671-
val color = if (addressNotification.isSuccess) {
672-
colorResource(id = R.color.woo_shipping_label_success)
673-
} else {
674-
colorResource(id = R.color.woo_shipping_label_error)
675-
}
676-
677-
val backgroundColor = if (addressNotification.isSuccess) {
678-
colorResource(id = R.color.woo_shipping_label_success_surface)
679-
} else {
680-
colorResource(id = R.color.woo_shipping_label_error_surface)
681-
}
682-
683-
val icon = if (addressNotification.isSuccess) {
684-
Icons.Outlined.CheckCircleOutline
685-
} else {
686-
Icons.Outlined.Info
687-
}
688-
689-
val configuration = LocalConfiguration.current
690-
val rowModifier = when (configuration.orientation) {
691-
Configuration.ORIENTATION_LANDSCAPE -> {
692-
modifier.widthIn(max = 600.dp).fillMaxWidth()
693-
}
694-
else -> {
695-
modifier.fillMaxWidth()
696-
}
697-
}
698-
699-
Row(
700-
rowModifier
701-
.padding(dimensionResource(R.dimen.major_100))
702-
.background(
703-
color = backgroundColor,
704-
shape = RoundedCornerShape(dimensionResource(R.dimen.corner_radius_large))
705-
)
706-
.clickable { onAction() }
707-
.padding(vertical = 8.dp, horizontal = 16.dp),
708-
verticalAlignment = Alignment.CenterVertically
709-
) {
710-
Icon(
711-
imageVector = icon,
712-
contentDescription = null,
713-
tint = color,
714-
modifier = Modifier.padding(end = 8.dp)
715-
)
716-
Text(
717-
text = stringResource(addressNotification.message),
718-
color = color,
719-
modifier = Modifier.weight(1f)
720-
)
721-
if (addressNotification.isSuccess.not()) {
722-
Icon(
723-
imageVector = Icons.Outlined.Close,
724-
contentDescription = null,
725-
tint = color,
726-
modifier = Modifier.clickable { onDismiss() }
727-
)
728-
}
729-
}
730-
}
731-
}
732-
}
733-
734531
@Preview
735532
@Composable
736533
private fun ShipmentCostSectionPreview() {
@@ -771,11 +568,6 @@ data class ShippingRateSummaryUI(
771568
val optionFee: String? = null
772569
) : Parcelable
773570

774-
data class ItnMissingNotification(
775-
val errorMessage: String,
776-
val onErrorDismissed: () -> Unit
777-
)
778-
779571
@Composable
780572
fun VerticalDivider(
781573
modifier: Modifier = Modifier,

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/WooShippingLabelCreationScreen.kt

+2-20
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,7 @@ fun WooShippingLabelCreationScreen(viewModel: WooShippingLabelCreationViewModel)
123123
onEditDestinationAddress = viewModel::onEditDestinationAddress,
124124
destinationStatus = viewState.destinationStatus,
125125
actionSnackbar = viewModel.actionSnackbar,
126-
onDismissAddressNotification = viewModel::onDismissAddressNotification,
127126
onSplitShipment = viewModel::onSplitShipment,
128-
onDismissItnNotice = viewModel::onDismissItnNotice
129127
)
130128
}
131129

@@ -165,11 +163,9 @@ fun WooShippingLabelCreationScreen(
165163
onEditCustomsClick: () -> Unit,
166164
onNavigateBack: () -> Unit,
167165
onEditDestinationAddress: (DestinationShippingAddress) -> Unit,
168-
onDismissItnNotice: () -> Unit,
169166
destinationStatus: AddressStatus,
170167
modifier: Modifier = Modifier,
171168
actionSnackbar: ActionSnackbar? = null,
172-
onDismissAddressNotification: () -> Unit = {},
173169
onSplitShipment: () -> Unit = {}
174170
) {
175171
val shipmentDetailsValue = if (uiState.isShipmentDetailsExpanded) {
@@ -232,8 +228,6 @@ fun WooShippingLabelCreationScreen(
232228
onShipmentDetailsExpandedChange = onShipmentDetailsExpandedChange,
233229
onEditCustomsClick = onEditCustomsClick,
234230
onEditDestinationAddress = onEditDestinationAddress,
235-
onDismissItnNotice = onDismissItnNotice,
236-
onDismissAddressNotification = onDismissAddressNotification,
237231
destinationStatus = destinationStatus,
238232
actionSnackbar = actionSnackbar,
239233
onSplitShipment = onSplitShipment
@@ -312,18 +306,15 @@ private fun LabelCreationScreenWithBottomSheet(
312306
onShipmentDetailsExpandedChange: (Boolean) -> Boolean,
313307
onEditCustomsClick: () -> Unit,
314308
onEditDestinationAddress: (DestinationShippingAddress) -> Unit,
315-
onDismissItnNotice: () -> Unit,
316309
destinationStatus: AddressStatus,
317310
modifier: Modifier = Modifier,
318-
onDismissAddressNotification: () -> Unit = {},
319311
actionSnackbar: ActionSnackbar? = null,
320312
onSplitShipment: () -> Unit = {}
321313
) {
322314
val snackbarHostState = remember { SnackbarHostState() }
323315

324-
val isItnMissing = customsState is ItnMissing
325316
val isPurchaseButtonDisplayed = shippingRatesState is WooShippingLabelCreationViewModel.ShippingRatesState.DataState
326-
val requiresLargePeekHeight = isPurchaseButtonDisplayed || uiState.addressNotification != null || isItnMissing
317+
val requiresLargePeekHeight = isPurchaseButtonDisplayed || uiState.noticeBannerUiState != null
327318

328319
val bottomSheetPeekHeight = when {
329320
requiresLargePeekHeight -> 128.dp
@@ -371,15 +362,7 @@ private fun LabelCreationScreenWithBottomSheet(
371362
onShipmentDetailsExpandedChange = onShipmentDetailsExpandedChange,
372363
onEditDestinationAddress = onEditDestinationAddress,
373364
destinationStatus = destinationStatus,
374-
addressNotification = uiState.addressNotification,
375-
onDismissAddressNotification = onDismissAddressNotification,
376-
onEditOriginAddress = onEditOriginAddress,
377-
itnNotification = takeIf { isItnMissing }?.let {
378-
ItnMissingNotification(
379-
errorMessage = stringResource(R.string.woo_shipping_labels_customs_itn_required_error),
380-
onErrorDismissed = onDismissItnNotice
381-
)
382-
}
365+
noticeBannerUiState = uiState.noticeBannerUiState
383366
)
384367
}
385368
},
@@ -894,7 +877,6 @@ private fun WooShippingLabelCreationScreenPreview() {
894877
onSelectAddressExpandedChange = { true },
895878
onEditCustomsClick = {},
896879
onEditDestinationAddress = {},
897-
onDismissItnNotice = {},
898880
destinationStatus = AddressStatus.VERIFIED
899881
)
900882
}

0 commit comments

Comments
 (0)