Skip to content

Commit 9947930

Browse files
[Shipping Labels] Split shipment navigation (#15369)
2 parents 1269cd4 + da2e8b2 commit 9947930

File tree

6 files changed

+200
-0
lines changed

6 files changed

+200
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import SwiftUI
2+
3+
struct WooShippingSplitShipmentsDetailView: View {
4+
@Environment(\.dismiss) private var dismiss
5+
6+
let viewModel: WooShippingSplitShipmentsViewModel
7+
8+
var body: some View {
9+
NavigationView {
10+
ScrollView {
11+
VStack(alignment: .leading, spacing: Layout.contentPadding) {
12+
AdaptiveStack(horizontalAlignment: .leading) {
13+
Text(viewModel.itemsCountLabel)
14+
.headlineStyle()
15+
Spacer()
16+
Text(viewModel.itemsDetailLabel)
17+
.foregroundStyle(Color(.textSubtle))
18+
}
19+
20+
VStack {
21+
ForEach(viewModel.items) { item in
22+
WooShippingItemRow(viewModel: item)
23+
.padding()
24+
.roundedBorder(cornerRadius: Layout.borderCornerRadius, lineColor: Color(.separator), lineWidth: Layout.borderWidth)
25+
}
26+
}
27+
}
28+
.padding(Layout.contentPadding)
29+
}
30+
.navigationBarTitleDisplayMode(.inline)
31+
.navigationTitle(Localization.title)
32+
.toolbar {
33+
ToolbarItem(placement: .cancellationAction) {
34+
Button(Localization.selectAll) {
35+
36+
}
37+
}
38+
ToolbarItem(placement: .confirmationAction) {
39+
Button(Localization.done) {
40+
dismiss()
41+
}
42+
}
43+
}
44+
}
45+
}
46+
}
47+
48+
private extension WooShippingSplitShipmentsDetailView {
49+
enum Layout {
50+
static let contentPadding: CGFloat = 16
51+
static let borderCornerRadius: CGFloat = 8
52+
static let borderWidth: CGFloat = 0.5
53+
}
54+
enum Localization {
55+
static let title = NSLocalizedString(
56+
"wooShippingSplitShipmentsDetailView.title",
57+
value: "Split Shipments",
58+
comment: "Title of the split shipments detail view in the shipping label creation flow"
59+
)
60+
static let selectAll = NSLocalizedString(
61+
"wooShippingSplitShipmentsDetailView.selectAll",
62+
value: "Select All",
63+
comment: "Button to select all items in the shipment detail in the shipping label creation flow"
64+
)
65+
static let done = NSLocalizedString(
66+
"wooShippingSplitShipmentsDetailView.done",
67+
value: "Done",
68+
comment: "Button to save split shipment configurations in the shipping label creation flow"
69+
)
70+
}
71+
}
72+
73+
#Preview {
74+
WooShippingSplitShipmentsDetailView(viewModel: WooShippingSplitShipmentsViewModel(siteID: 123,
75+
orderID: 123))
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import SwiftUI
2+
3+
struct WooShippingSplitShipmentsRow: View {
4+
@State private var isShowingDetailView = false
5+
6+
let viewModel: WooShippingSplitShipmentsViewModel
7+
8+
init(viewModel: WooShippingSplitShipmentsViewModel) {
9+
self.viewModel = viewModel
10+
}
11+
12+
var body: some View {
13+
AdaptiveStack {
14+
Text(Localization.products)
15+
.tertiaryTitleStyle()
16+
Spacer()
17+
Button(Localization.splitShipments) {
18+
isShowingDetailView = true
19+
}
20+
.buttonStyle(TextButtonStyle())
21+
}
22+
.padding(.vertical, Layout.verticalPadding)
23+
.fullScreenCover(isPresented: $isShowingDetailView) {
24+
WooShippingSplitShipmentsDetailView(viewModel: viewModel)
25+
}
26+
}
27+
}
28+
29+
private extension WooShippingSplitShipmentsRow {
30+
enum Layout {
31+
static let verticalPadding: CGFloat = 16
32+
}
33+
34+
enum Localization {
35+
static let products = NSLocalizedString("wooShipping.splitShipments.products",
36+
value: "Products",
37+
comment: "Label for section in shipping label creation to split shipments.")
38+
39+
static let splitShipments = NSLocalizedString("wooShipping.splitShipments.splitShipmentsButtonTitle",
40+
value: "Split shipments",
41+
comment: "Title for button in shipping label creation to start split shipments flow.")
42+
}
43+
}
44+
45+
#Preview {
46+
WooShippingSplitShipmentsRow(viewModel: WooShippingSplitShipmentsViewModel(siteID: 123,
47+
orderID: 123))
48+
.padding()
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import SwiftUI
2+
import Yosemite
3+
import WooFoundation
4+
5+
final class WooShippingSplitShipmentsViewModel: ObservableObject {
6+
private let siteID: Int64
7+
private let orderID: Int64
8+
private let stores: StoresManager
9+
10+
/// Label for the total number of items
11+
let itemsCountLabel = "6 items"
12+
13+
/// Label for the total item details
14+
let itemsDetailLabel = "825g · $135.00"
15+
16+
let items: [WooShippingItemRowViewModel] = [WooShippingItemRowViewModel(imageUrl: nil,
17+
quantityLabel: "3",
18+
name: "Little Nap Brazil 250g",
19+
detailsLabel: "15×10×8cm • Espresso",
20+
weightLabel: "275g",
21+
priceLabel: "$60.00"),
22+
WooShippingItemRowViewModel(imageUrl: nil,
23+
quantityLabel: "3",
24+
name: "Little Nap Brazil 250g",
25+
detailsLabel: "15×10×8cm • Espresso",
26+
weightLabel: "275g",
27+
priceLabel: "$60.00")]
28+
init(siteID: Int64,
29+
orderID: Int64,
30+
stores: StoresManager = ServiceLocator.stores) {
31+
self.siteID = siteID
32+
self.orderID = orderID
33+
self.stores = stores
34+
}
35+
}

WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ private extension WooShippingCreateLabelsView {
104104
WooShippingPostPurchaseView(viewModel: postPurchase)
105105
}
106106

107+
if let splitShipmentsViewModel = viewModel.splitShipmentsViewModel {
108+
WooShippingSplitShipmentsRow(viewModel: splitShipmentsViewModel)
109+
}
110+
107111
WooShippingItems(viewModel: viewModel.items)
108112

109113
WooShippingHazmatRow(isHazardous: $viewModel.containsHazardousMaterials,

WooCommerce/Classes/ViewRelated/Orders/Order Details/Shipping Labels/WooShipping Create Shipping Labels/WooShippingCreateLabelsViewModel.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
6262
/// View model for the label shipping service.
6363
private(set) var shippingService: WooShippingServiceViewModel?
6464

65+
/// View model for split shipments.
66+
private(set) var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel?
67+
6568
/// Selected shipping rate when creating a shipping label.
6669
@Published private var selectedRate: WooShippingSelectedRate?
6770

@@ -269,6 +272,10 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
269272
await self.loadOriginAddresses()
270273
}
271274
}
275+
276+
group.addTask {
277+
await self.loadShipmentsInfo()
278+
}
272279
}
273280

274281
if isMissingStoreSettings ||
@@ -416,6 +423,15 @@ private extension WooShippingCreateLabelsViewModel {
416423
}
417424
}
418425

426+
/// Loads shipment info from remote and creates view model for split shipments.
427+
///
428+
@MainActor
429+
func loadShipmentsInfo() async {
430+
splitShipmentsViewModel = WooShippingSplitShipmentsViewModel(siteID: order.siteID,
431+
orderID: order.orderID,
432+
stores: stores)
433+
}
434+
419435
/// Loads destination address of the order from remote.
420436
///
421437
func loadDestinationAddress() {

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2992,6 +2992,9 @@
29922992
EE66BB102B29D24600518DAF /* DefaultThemeInstallerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE66BB0F2B29D24600518DAF /* DefaultThemeInstallerTests.swift */; };
29932993
EE66BB122B29D65400518DAF /* MockThemeInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE66BB112B29D65400518DAF /* MockThemeInstaller.swift */; };
29942994
EE6C6B6E2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE6C6B6D2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift */; };
2995+
EE7E75A82D83EB1F00E6FF5B /* WooShippingSplitShipmentsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */; };
2996+
EE7E75AA2D84066C00E6FF5B /* WooShippingSplitShipmentsDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */; };
2997+
EE7E75AC2D84080D00E6FF5B /* WooShippingSplitShipmentsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */; };
29952998
EE81B1382865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */; };
29962999
EE8A302B2B70B63E001D7C66 /* MockImageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8A302A2B70B63E001D7C66 /* MockImageService.swift */; };
29973000
EE8A30452B74948C001D7C66 /* OrderAttributionInfo+Origin.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8A30442B74948C001D7C66 /* OrderAttributionInfo+Origin.swift */; };
@@ -6193,6 +6196,9 @@
61936196
EE66BB0F2B29D24600518DAF /* DefaultThemeInstallerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultThemeInstallerTests.swift; sourceTree = "<group>"; };
61946197
EE66BB112B29D65400518DAF /* MockThemeInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockThemeInstaller.swift; sourceTree = "<group>"; };
61956198
EE6C6B6D2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaLibraryPickerDataSourceTests.swift; sourceTree = "<group>"; };
6199+
EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsRow.swift; sourceTree = "<group>"; };
6200+
EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsDetailView.swift; sourceTree = "<group>"; };
6201+
EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsViewModel.swift; sourceTree = "<group>"; };
61966202
EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductImagesProductIDUpdaterTests.swift; sourceTree = "<group>"; };
61976203
EE8A302A2B70B63E001D7C66 /* MockImageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageService.swift; sourceTree = "<group>"; };
61986204
EE8A30442B74948C001D7C66 /* OrderAttributionInfo+Origin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderAttributionInfo+Origin.swift"; sourceTree = "<group>"; };
@@ -12457,6 +12463,7 @@
1245712463
CEAB739A2C81E3A000A7EB39 /* WooShipping Create Shipping Labels */ = {
1245812464
isa = PBXGroup;
1245912465
children = (
12466+
EE7E75A62D83EAD200E6FF5B /* WooShipping Split Shipments */,
1246012467
B90DD08C2D12FA6600EFC06A /* WooShipping Customs */,
1246112468
CE6E11092C91DA3D00563DD4 /* WooShipping Items Section */,
1246212469
CE7B4A592CA1BF7800F764EB /* WooShipping Hazmat Section */,
@@ -13963,6 +13970,16 @@
1396313970
path = AIToneVoice;
1396413971
sourceTree = "<group>";
1396513972
};
13973+
EE7E75A62D83EAD200E6FF5B /* WooShipping Split Shipments */ = {
13974+
isa = PBXGroup;
13975+
children = (
13976+
EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */,
13977+
EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */,
13978+
EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */,
13979+
);
13980+
path = "WooShipping Split Shipments";
13981+
sourceTree = "<group>";
13982+
};
1396613983
EE8B420A2BF9A1E40077C4E7 /* Orders */ = {
1396713984
isa = PBXGroup;
1396813985
children = (
@@ -16514,6 +16531,7 @@
1651416531
26E0AE13263359F900A5EB3B /* View+Conditionals.swift in Sources */,
1651516532
68F151E12C0DA7910082AEC8 /* CartItem.swift in Sources */,
1651616533
CE583A072107849F00D73C1C /* SwitchTableViewCell.swift in Sources */,
16534+
EE7E75A82D83EB1F00E6FF5B /* WooShippingSplitShipmentsRow.swift in Sources */,
1651716535
D8149F562251EE300006A245 /* UITextField+Helpers.swift in Sources */,
1651816536
20762BA52C18B42C00758305 /* CardPresentPaymentBluetoothReaderConnectionAlertsProvider.swift in Sources */,
1651916537
0212276124498A270042161F /* ProductFormBottomSheetListSelectorCommand.swift in Sources */,
@@ -16624,6 +16642,7 @@
1662416642
025FDD3223717D2900824006 /* EditorFactory.swift in Sources */,
1662516643
45D1CF4723BAC89A00945A36 /* ProductTaxStatusListSelectorCommand.swift in Sources */,
1662616644
453DBF9023882814006762A5 /* ProductImagesFlowLayout.swift in Sources */,
16645+
EE7E75AA2D84066C00E6FF5B /* WooShippingSplitShipmentsDetailView.swift in Sources */,
1662716646
024DF30E23742A70006658FE /* AztecBoldFormatBarCommand.swift in Sources */,
1662816647
DEE6437826D8DAD900888A75 /* InProgressView.swift in Sources */,
1662916648
0290E275238E4F8100B5C466 /* PaginatedListSelectorViewController.swift in Sources */,
@@ -17216,6 +17235,7 @@
1721617235
02DE5CA9279F857D007CBEF3 /* Double+Rounding.swift in Sources */,
1721717236
B9CCE5FC2C8753A000905A91 /* ProductBarcodeScannerProvider.swift in Sources */,
1721817237
02A65301246AA63600755A01 /* ProductDetailsFactory.swift in Sources */,
17238+
EE7E75AC2D84080D00E6FF5B /* WooShippingSplitShipmentsViewModel.swift in Sources */,
1721917239
D449C51D26DE6B5000D75B02 /* LargeTitle.swift in Sources */,
1722017240
B6E7DB64293A7C390049B001 /* AnalyticsHubYesterdayRangeData.swift in Sources */,
1722117241
456396B625C82691001F1A26 /* ShippingLabelFormStepTableViewCell.swift in Sources */,

0 commit comments

Comments
 (0)