Skip to content

Commit

Permalink
[Shipping labels] Edit selected package (#14713)
Browse files Browse the repository at this point in the history
  • Loading branch information
rachelmcr authored Dec 19, 2024
2 parents 5a7a18b + b16aa65 commit 07fff78
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ enum WooShippingPackageSource {
return sourceTitle
}
}

var sourceID: String? {
guard case .predefined(_, let sourceID) = self else {
return nil
}
return sourceID
}
}

protocol WooShippingPackageDataRepresentable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,31 @@ final class WooShippingAddCustomPackageViewModel: ObservableObject {
// Holds values for all dimension input fields.
// Using a dictionary so we can easily add/remove new types
// if needed just by adding new case in enum
@Published var fieldValues: [WooShippingPackageUnitType: String] = [:]
@Published var fieldValues: [WooShippingPackageUnitType: String]
// Holds selected package type when custom package is selected, it can be `box` or `envelope`
@Published var packageType: WooShippingPackageType = .box
@Published var packageType: WooShippingPackageType
// Holds value for toggle that determines if we are showing button for saving the template
@Published var showSaveTemplate: Bool = false
@Published var packageTemplateName: String = ""

// MARK: Initialization

init(siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
init(selectedPackage: WooShippingPackageDataRepresentable? = nil,
siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
stores: StoresManager = ServiceLocator.stores) {
self.stores = stores
self.siteID = siteID
if let selectedPackage {
fieldValues = [
.length: selectedPackage.length,
.width: selectedPackage.width,
.height: selectedPackage.height
]
packageType = WooShippingPackageType(rawValue: selectedPackage.packageType) ?? .box
} else {
fieldValues = [:]
packageType = .box
}
}

// Field values are invalid if one of them is empty
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import SwiftUI
import Combine
import struct Yosemite.ShippingLabelStoreOptions

struct WooShippingAddPackageView: View {
enum PackageProviderType: CaseIterable {
Expand All @@ -18,11 +17,8 @@ struct WooShippingAddPackageView: View {
}

@Environment(\.presentationMode) var presentationMode

// Holds type of selected package, it can be `custom`, `carrier` or `saved`
@State var selectedPackageType = PackageProviderType.custom
@StateObject var packagesViewModel = WooShippingAddPackageViewModel()
@State var customPackageViewModel = WooShippingAddCustomPackageViewModel()
@ObservedObject var packagesViewModel: WooShippingAddPackageViewModel
@ObservedObject var customPackageViewModel: WooShippingAddCustomPackageViewModel

let addPackageAction: (WooShippingPackageDataRepresentable) -> Void

Expand All @@ -31,16 +27,24 @@ struct WooShippingAddPackageView: View {
@Environment(\.shippingWeightUnit) private var weightUnit
@Environment(\.shippingDimensionsUnit) private var dimensionsUnit

init(addPackageAction: @escaping (WooShippingPackageDataRepresentable) -> Void) {
init(selectedPackage: WooShippingPackageDataRepresentable? = nil,
addPackageAction: @escaping (WooShippingPackageDataRepresentable) -> Void) {
self.addPackageAction = addPackageAction
packagesViewModel = WooShippingAddPackageViewModel(selectedPackage: selectedPackage)
switch selectedPackage?.source {
case .custom:
customPackageViewModel = WooShippingAddCustomPackageViewModel(selectedPackage: selectedPackage)
default:
customPackageViewModel = WooShippingAddCustomPackageViewModel()
}
}

// MARK: - UI

var body: some View {
NavigationView {
VStack {
Picker("", selection: $selectedPackageType) {
Picker("", selection: $packagesViewModel.selectedPackageType) {
ForEach(PackageProviderType.allCases, id: \.self) {
Text($0.name)
}
Expand Down Expand Up @@ -68,7 +72,7 @@ struct WooShippingAddPackageView: View {

@ViewBuilder
private var selectedPackageTypeView: some View {
switch selectedPackageType {
switch packagesViewModel.selectedPackageType {
case .custom:
WooAddCustomPackageView(viewModel: customPackageViewModel,
addPackageAction: addPackageAction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,37 @@ final class WooShippingAddPackageViewModel: ObservableObject {

private let starAnimation: Animation = .spring(duration: 0.2)

init(siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
// Holds type of selected package, it can be `custom`, `carrier` or `saved`
@Published var selectedPackageType: WooShippingAddPackageView.PackageProviderType

init(selectedPackage: WooShippingPackageDataRepresentable? = nil,
siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
stores: StoresManager = ServiceLocator.stores,
storage: StorageManagerType = ServiceLocator.storageManager) {
self.siteID = siteID
self.stores = stores
self.storage = storage
selectedPackageType = .custom
previousSelectedPackage = selectedPackage
// Optimistically set the selected package ID.
// We will select the correct package type (custom, carrier or saved) after loading the packages.
switch selectedPackage?.source {
case .custom:
selectedSavedPackageId = selectedPackage?.id
case .predefined:
selectedCarriersPackageId = selectedPackage?.id
selectedSavedPackageId = selectedPackage?.id
case nil:
break
}
configureResultsController()
}

@Published private(set) var isLoadingPackages: Bool = false

/// Holds the previously selected package data, which can be transformed e.g. to select the correct tabs in the view.
private let previousSelectedPackage: WooShippingPackageDataRepresentable?

// MARK: - saved

@Published var selectedSavedPackageId: String? = nil // Track the selected package index
Expand Down Expand Up @@ -157,8 +177,25 @@ final class WooShippingAddPackageViewModel: ObservableObject {

starredCarriersPackages = Set(predefinedSavedPackages.map { $0.id })

// Select package type matching the previous selected package, if it is the currently selected package
if let previousSelectedPackage, previousSelectedPackage.id == selectedSavedPackageId || previousSelectedPackage.id == selectedCarriersPackageId {
switch previousSelectedPackage.source {
case .predefined:
selectedPackageType = predefinedSavedPackages.contains(where: { $0.id == previousSelectedPackage.id }) ? .saved : .carrier
case .custom:
selectedPackageType = customSavedPackages.contains(where: { $0.id == previousSelectedPackage.id }) ? .saved : .custom
}
}

if selectedCarriersTabIndex == nil {
self.selectedCarriersTabIndex = carrierPackages.isEmpty ? nil : 0
// Select the carriers tab matching the previous selected carriers package, if it is the currently selected package
if let previousSelectedPackage, selectedCarriersPackageId == previousSelectedPackage.id {
selectedCarriersTabIndex = carrierPackages.firstIndex { carrierTab in
return carrierTab.carrier.rawValue == previousSelectedPackage.source.sourceID
}
} else {
selectedCarriersTabIndex = carrierPackages.isEmpty ? nil : 0
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ struct WooShippingPackageAndRatePlaceholder: View {
let onSelectPackage: (WooShippingPackageDataRepresentable) -> Void

@State private var showAddPackage: Bool = false
@ObservedObject var viewModel: WooShippingCreateLabelsViewModel

var body: some View {
VStack(spacing: .zero) {
Expand Down Expand Up @@ -67,8 +66,7 @@ private extension WooShippingPackageAndRatePlaceholder {
import struct Yosemite.Order

#Preview {
WooShippingPackageAndRatePlaceholder(onSelectPackage: { _ in },
viewModel: WooShippingCreateLabelsViewModel(order: Order.sampleOrder))
WooShippingPackageAndRatePlaceholder(onSelectPackage: { _ in })
.padding()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ struct WooShippingSelectedPackageView: View {

@Environment(\.shippingWeightUnit) private var weightUnit

@State private var showPackageSelection = false

/// Closure to perform when a new package is selected.
let updateSelectedPackage: (WooShippingPackageDataRepresentable) -> Void

var body: some View {
VStack(alignment: .leading) {
HStack {
Text(Localization.package)
.headlineStyle()
Spacer()
PencilEditButton {
// TODO: Edit selected package
showPackageSelection = true
}
.buttonStyle(TextButtonStyle())
}
Expand All @@ -25,6 +30,12 @@ struct WooShippingSelectedPackageView: View {
.padding(.bottom)
shipmentWeight
}
.sheet(isPresented: $showPackageSelection) {
WooShippingAddPackageView(selectedPackage: package) { newPackage in
updateSelectedPackage(newPackage)
showPackageSelection = false
}
}
}

private var shipmentWeight: some View {
Expand Down Expand Up @@ -70,7 +81,8 @@ private extension WooShippingSelectedPackageView {
weight: "4",
source: .predefined(sourceTitle: "USPS Priority Mail Flat Rate Boxes", sourceID: "usps"),
packageType: "box"),
totalWeight: .constant("6"))
totalWeight: .constant("6"),
updateSelectedPackage: { _ in })
.shippingDimensionsUnit("in")
.shippingWeightUnit("lb")
}
Expand All @@ -83,7 +95,8 @@ private extension WooShippingSelectedPackageView {
weight: "",
source: .custom,
packageType: "box"),
totalWeight: .constant("6"))
totalWeight: .constant("6"),
updateSelectedPackage: { _ in })
.shippingDimensionsUnit("in")
.shippingWeightUnit("lb")
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ struct WooShippingCreateLabelsView: View {
} else if let package = viewModel.selectedPackage,
let shippingService = viewModel.shippingService {
WooShippingSelectedPackageView(package: package,
totalWeight: $viewModel.shipmentWeight)
totalWeight: $viewModel.shipmentWeight,
updateSelectedPackage: viewModel.selectPackage)
WooShippingServiceView(viewModel: shippingService)
.padding(.horizontal, -16)
} else {
WooShippingPackageAndRatePlaceholder(onSelectPackage: viewModel.selectPackage, viewModel: viewModel)
WooShippingPackageAndRatePlaceholder(onSelectPackage: viewModel.selectPackage)
}
}
.padding(16)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,26 @@ final class WooShippingAddCustomPackageViewModelTests: XCTestCase {
XCTFail(failure.localizedDescription)
}
}

func test_it_handles_selected_package_data() {
// Given
let selectedPackage = WooShippingPackageData(name: "",
length: "31.75",
width: "24.13",
height: "1.27",
weight: "",
source: .custom,
packageType: "envelope")

// When
let viewModel = WooShippingAddCustomPackageViewModel(selectedPackage: selectedPackage)

// Then
XCTAssertEqual(viewModel.fieldValues[.length], "31.75")
XCTAssertEqual(viewModel.fieldValues[.width], "24.13")
XCTAssertEqual(viewModel.fieldValues[.height], "1.27")
XCTAssertEqual(viewModel.packageType, .envelope)
}
}

extension WooShippingAddCustomPackageViewModel {
Expand Down
Loading

0 comments on commit 07fff78

Please sign in to comment.