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
@@ -0,0 +1,76 @@
import SwiftUI

struct WooShippingSplitShipmentsDetailView: View {
@Environment(\.dismiss) private var dismiss

let viewModel: WooShippingSplitShipmentsViewModel

var body: some View {
NavigationView {
ScrollView {
VStack(alignment: .leading, spacing: Layout.contentPadding) {
AdaptiveStack(horizontalAlignment: .leading) {
Text(viewModel.itemsCountLabel)
.headlineStyle()
Spacer()
Text(viewModel.itemsDetailLabel)
.foregroundStyle(Color(.textSubtle))
}

VStack {
ForEach(viewModel.items) { item in
WooShippingItemRow(viewModel: item)
.padding()
.roundedBorder(cornerRadius: Layout.borderCornerRadius, lineColor: Color(.separator), lineWidth: Layout.borderWidth)
}
}
}
.padding(Layout.contentPadding)
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(Localization.title)
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button(Localization.selectAll) {

}
}
ToolbarItem(placement: .confirmationAction) {
Button(Localization.done) {
dismiss()
}
}
}
}
}
}

private extension WooShippingSplitShipmentsDetailView {
enum Layout {
static let contentPadding: CGFloat = 16
static let borderCornerRadius: CGFloat = 8
static let borderWidth: CGFloat = 0.5
}
enum Localization {
static let title = NSLocalizedString(
"wooShippingSplitShipmentsDetailView.title",
value: "Split Shipments",
comment: "Title of the split shipments detail view in the shipping label creation flow"
)
static let selectAll = NSLocalizedString(
"wooShippingSplitShipmentsDetailView.selectAll",
value: "Select All",
comment: "Button to select all items in the shipment detail in the shipping label creation flow"
)
static let done = NSLocalizedString(
"wooShippingSplitShipmentsDetailView.done",
value: "Done",
comment: "Button to save split shipment configurations in the shipping label creation flow"
)
}
}

#Preview {
WooShippingSplitShipmentsDetailView(viewModel: WooShippingSplitShipmentsViewModel(siteID: 123,
orderID: 123))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import SwiftUI

struct WooShippingSplitShipmentsRow: View {
@State private var isShowingDetailView = false

let viewModel: WooShippingSplitShipmentsViewModel

init(viewModel: WooShippingSplitShipmentsViewModel) {
self.viewModel = viewModel
}

var body: some View {
AdaptiveStack {
Text(Localization.products)
.tertiaryTitleStyle()
Spacer()
Button(Localization.splitShipments) {
isShowingDetailView = true
}
.buttonStyle(TextButtonStyle())
}
.padding(.vertical, Layout.verticalPadding)
.fullScreenCover(isPresented: $isShowingDetailView) {
WooShippingSplitShipmentsDetailView(viewModel: viewModel)
}
}
}

private extension WooShippingSplitShipmentsRow {
enum Layout {
static let verticalPadding: CGFloat = 16
}

enum Localization {
static let products = NSLocalizedString("wooShipping.splitShipments.products",
value: "Products",
comment: "Label for section in shipping label creation to split shipments.")

static let splitShipments = NSLocalizedString("wooShipping.splitShipments.splitShipmentsButtonTitle",
value: "Split shipments",
comment: "Title for button in shipping label creation to start split shipments flow.")
}
}

#Preview {
WooShippingSplitShipmentsRow(viewModel: WooShippingSplitShipmentsViewModel(siteID: 123,
orderID: 123))
.padding()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import SwiftUI
import Yosemite
import WooFoundation

final class WooShippingSplitShipmentsViewModel: ObservableObject {
private let siteID: Int64
private let orderID: Int64
private let stores: StoresManager

/// Label for the total number of items
let itemsCountLabel = "6 items"

/// Label for the total item details
let itemsDetailLabel = "825g · $135.00"

let items: [WooShippingItemRowViewModel] = [WooShippingItemRowViewModel(imageUrl: nil,
quantityLabel: "3",
name: "Little Nap Brazil 250g",
detailsLabel: "15×10×8cm • Espresso",
weightLabel: "275g",
priceLabel: "$60.00"),
WooShippingItemRowViewModel(imageUrl: nil,
quantityLabel: "3",
name: "Little Nap Brazil 250g",
detailsLabel: "15×10×8cm • Espresso",
weightLabel: "275g",
priceLabel: "$60.00")]
init(siteID: Int64,
orderID: Int64,
stores: StoresManager = ServiceLocator.stores) {
self.siteID = siteID
self.orderID = orderID
self.stores = stores
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ private extension WooShippingCreateLabelsView {
WooShippingPostPurchaseView(viewModel: postPurchase)
}

if let splitShipmentsViewModel = viewModel.splitShipmentsViewModel {
WooShippingSplitShipmentsRow(viewModel: splitShipmentsViewModel)
}

WooShippingItems(viewModel: viewModel.items)

WooShippingHazmatRow(isHazardous: $viewModel.containsHazardousMaterials,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
/// View model for the label shipping service.
private(set) var shippingService: WooShippingServiceViewModel?

/// View model for split shipments.
private(set) var splitShipmentsViewModel: WooShippingSplitShipmentsViewModel?

/// Selected shipping rate when creating a shipping label.
@Published private var selectedRate: WooShippingSelectedRate?

Expand Down Expand Up @@ -269,6 +272,10 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
await self.loadOriginAddresses()
}
}

group.addTask {
await self.loadShipmentsInfo()
}
}

if isMissingStoreSettings ||
Expand Down Expand Up @@ -416,6 +423,15 @@ private extension WooShippingCreateLabelsViewModel {
}
}

/// Loads shipment info from remote and creates view model for split shipments.
///
@MainActor
func loadShipmentsInfo() async {
splitShipmentsViewModel = WooShippingSplitShipmentsViewModel(siteID: order.siteID,
orderID: order.orderID,
stores: stores)
}
Comment on lines +428 to +433
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this also WIP? Should we disable splitting if an order has only one item?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Yes, this is WIP.

We need to load the shipment info from the remote and show this "Split shipments" view. I will update this after adding endpoint support in #15370.


/// Loads destination address of the order from remote.
///
func loadDestinationAddress() {
Expand Down
20 changes: 20 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2992,6 +2992,9 @@
EE66BB102B29D24600518DAF /* DefaultThemeInstallerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE66BB0F2B29D24600518DAF /* DefaultThemeInstallerTests.swift */; };
EE66BB122B29D65400518DAF /* MockThemeInstaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE66BB112B29D65400518DAF /* MockThemeInstaller.swift */; };
EE6C6B6E2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE6C6B6D2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift */; };
EE7E75A82D83EB1F00E6FF5B /* WooShippingSplitShipmentsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */; };
EE7E75AA2D84066C00E6FF5B /* WooShippingSplitShipmentsDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */; };
EE7E75AC2D84080D00E6FF5B /* WooShippingSplitShipmentsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */; };
EE81B1382865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */; };
EE8A302B2B70B63E001D7C66 /* MockImageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8A302A2B70B63E001D7C66 /* MockImageService.swift */; };
EE8A30452B74948C001D7C66 /* OrderAttributionInfo+Origin.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE8A30442B74948C001D7C66 /* OrderAttributionInfo+Origin.swift */; };
Expand Down Expand Up @@ -6193,6 +6196,9 @@
EE66BB0F2B29D24600518DAF /* DefaultThemeInstallerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultThemeInstallerTests.swift; sourceTree = "<group>"; };
EE66BB112B29D65400518DAF /* MockThemeInstaller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockThemeInstaller.swift; sourceTree = "<group>"; };
EE6C6B6D2C65DC4100632BDA /* WordPressMediaLibraryPickerDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressMediaLibraryPickerDataSourceTests.swift; sourceTree = "<group>"; };
EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsRow.swift; sourceTree = "<group>"; };
EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsDetailView.swift; sourceTree = "<group>"; };
EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingSplitShipmentsViewModel.swift; sourceTree = "<group>"; };
EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductImagesProductIDUpdaterTests.swift; sourceTree = "<group>"; };
EE8A302A2B70B63E001D7C66 /* MockImageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockImageService.swift; sourceTree = "<group>"; };
EE8A30442B74948C001D7C66 /* OrderAttributionInfo+Origin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderAttributionInfo+Origin.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -12457,6 +12463,7 @@
CEAB739A2C81E3A000A7EB39 /* WooShipping Create Shipping Labels */ = {
isa = PBXGroup;
children = (
EE7E75A62D83EAD200E6FF5B /* WooShipping Split Shipments */,
B90DD08C2D12FA6600EFC06A /* WooShipping Customs */,
CE6E11092C91DA3D00563DD4 /* WooShipping Items Section */,
CE7B4A592CA1BF7800F764EB /* WooShipping Hazmat Section */,
Expand Down Expand Up @@ -13963,6 +13970,16 @@
path = AIToneVoice;
sourceTree = "<group>";
};
EE7E75A62D83EAD200E6FF5B /* WooShipping Split Shipments */ = {
isa = PBXGroup;
children = (
EE7E75AB2D84080A00E6FF5B /* WooShippingSplitShipmentsViewModel.swift */,
EE7E75A92D84066800E6FF5B /* WooShippingSplitShipmentsDetailView.swift */,
EE7E75A72D83EB0700E6FF5B /* WooShippingSplitShipmentsRow.swift */,
);
path = "WooShipping Split Shipments";
sourceTree = "<group>";
};
EE8B420A2BF9A1E40077C4E7 /* Orders */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -16514,6 +16531,7 @@
26E0AE13263359F900A5EB3B /* View+Conditionals.swift in Sources */,
68F151E12C0DA7910082AEC8 /* CartItem.swift in Sources */,
CE583A072107849F00D73C1C /* SwitchTableViewCell.swift in Sources */,
EE7E75A82D83EB1F00E6FF5B /* WooShippingSplitShipmentsRow.swift in Sources */,
D8149F562251EE300006A245 /* UITextField+Helpers.swift in Sources */,
20762BA52C18B42C00758305 /* CardPresentPaymentBluetoothReaderConnectionAlertsProvider.swift in Sources */,
0212276124498A270042161F /* ProductFormBottomSheetListSelectorCommand.swift in Sources */,
Expand Down Expand Up @@ -16624,6 +16642,7 @@
025FDD3223717D2900824006 /* EditorFactory.swift in Sources */,
45D1CF4723BAC89A00945A36 /* ProductTaxStatusListSelectorCommand.swift in Sources */,
453DBF9023882814006762A5 /* ProductImagesFlowLayout.swift in Sources */,
EE7E75AA2D84066C00E6FF5B /* WooShippingSplitShipmentsDetailView.swift in Sources */,
024DF30E23742A70006658FE /* AztecBoldFormatBarCommand.swift in Sources */,
DEE6437826D8DAD900888A75 /* InProgressView.swift in Sources */,
0290E275238E4F8100B5C466 /* PaginatedListSelectorViewController.swift in Sources */,
Expand Down Expand Up @@ -17216,6 +17235,7 @@
02DE5CA9279F857D007CBEF3 /* Double+Rounding.swift in Sources */,
B9CCE5FC2C8753A000905A91 /* ProductBarcodeScannerProvider.swift in Sources */,
02A65301246AA63600755A01 /* ProductDetailsFactory.swift in Sources */,
EE7E75AC2D84080D00E6FF5B /* WooShippingSplitShipmentsViewModel.swift in Sources */,
D449C51D26DE6B5000D75B02 /* LargeTitle.swift in Sources */,
B6E7DB64293A7C390049B001 /* AnalyticsHubYesterdayRangeData.swift in Sources */,
456396B625C82691001F1A26 /* ShippingLabelFormStepTableViewCell.swift in Sources */,
Expand Down