Skip to content

Commit

Permalink
[Shipping labels] Use stored packages in Woo Shipping package selecti…
Browse files Browse the repository at this point in the history
…on (#14711)
  • Loading branch information
rachelmcr authored Dec 19, 2024
2 parents 281110f + 7a09bb7 commit 5a7a18b
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,6 @@ struct WooShippingAddPackageView: View {
.navigationBarTitleDisplayMode(.inline)
}
.navigationViewStyle(.stack)
.task {
packagesViewModel.loadPackages()
}
}

// MARK: UI components
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@ import Foundation
import SwiftUI
import Combine
import Yosemite
import protocol Storage.StorageManagerType

final class WooShippingAddPackageViewModel: ObservableObject {
private let siteID: Int64
private let stores: StoresManager
private let storage: StorageManagerType

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

init(siteID: Int64 = ServiceLocator.stores.sessionManager.defaultStoreID ?? 0,
stores: StoresManager = ServiceLocator.stores) {
stores: StoresManager = ServiceLocator.stores,
storage: StorageManagerType = ServiceLocator.storageManager) {
self.siteID = siteID
self.stores = stores
self.storage = storage
configureResultsController()
}

@Published private(set) var isLoadingPackages: Bool = false
Expand Down Expand Up @@ -69,36 +74,57 @@ final class WooShippingAddPackageViewModel: ObservableObject {
return nil
}

// MARK: - Storage

/// Packages
///
private lazy var packagesResultsController: ResultsController<StorageWooShippingPackagesResponse> = {
let predicate = NSPredicate(format: "siteID == %lld", siteID)
return ResultsController<StorageWooShippingPackagesResponse>(storageManager: storage, matching: predicate, sortedBy: [])
}()

func configureResultsController() {
packagesResultsController.onDidChangeContent = transformLoadedPackages
packagesResultsController.onDidResetContent = transformLoadedPackages

do {
try packagesResultsController.performFetch()
transformLoadedPackages()
} catch {
ServiceLocator.crashLogging.logError(error)
}
}

// MARK: - loading

func loadPackages(completion: (() -> (Void))? = nil) {
guard !isLoadingPackages else { return }

isLoadingPackages = true

let loadPackagesAction = WooShippingAction.loadPackages(siteID: siteID) { result in
switch result {
case .success(let packagesResult):
self.transformLoadedPackages(packagesResult)
case .failure:
break
let loadPackagesAction = WooShippingAction.loadPackages(siteID: siteID) { [weak self] result in
guard let self else { return }
if case .failure(let error) = result {
DDLogError("⛔️ Error loading packages for Woo Shipping labels: \(error)")
}
self.isLoadingPackages = false
isLoadingPackages = false
completion?()
}

stores.dispatch(loadPackagesAction)
}

// transform packages
private func transformLoadedPackages(_ packagesResult: WooShippingPackagesResponse) {
let customSavedPackages = packagesResult.customPackages.map {
private func transformLoadedPackages() {
guard let packages = packagesResultsController.fetchedObjects.first else {
return
}
let customSavedPackages = packages.customPackages.map {
return $0.toPackageData()
}
let predefinedSavedPackages = packagesResult.savedPredefinedPackages.map {
let predefinedSavedPackages = packages.savedPredefinedPackages.map {
return $0.toPackageData()
}
var carrierPackages: [WooShippingCarrierPackages] = packagesResult.allPredefinedOptions.compactMap {
var carrierPackages: [WooShippingCarrierPackages] = packages.allPredefinedOptions.compactMap {
return $0.toCarrierPackages()
}
if self.carrierPackages.isNotEmpty {
Expand Down Expand Up @@ -127,7 +153,7 @@ final class WooShippingAddPackageViewModel: ObservableObject {
self.carrierPackages = carrierPackages
self.carrierTabs = carrierTabs

self.allPredefinedOptions = packagesResult.allPredefinedOptions
self.allPredefinedOptions = packages.allPredefinedOptions

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

Expand All @@ -136,42 +162,6 @@ final class WooShippingAddPackageViewModel: ObservableObject {
}
}

private func transformSavedPackages(_ response: WooShippingCreatePackageResponse) {
// helper function for creating jointIDs for easier checking if package should be used or not
func jointID(carrierID: String, packageID: String) -> String {
return "\(carrierID)-\(packageID)"
}

var jointIDs: [String] = []
for option in response.predefinedOptions {
for packageID in option.predefinedPackageIDs {
jointIDs.append(jointID(carrierID: option.id, packageID: packageID))
}
}

var allPredefinedSaved: [any WooShippingPackageDataRepresentable] = []

// use predefined saved packages from list of all packages
// since the response gives us IDs we need to get them manually from the list
for carrier in self.allPredefinedOptions {
let carrierID = carrier.carrierID
for option in carrier.predefinedOptions {
for package in option.predefinedPackages {
if jointIDs.contains(jointID(carrierID: carrierID, packageID: package.id)) {
allPredefinedSaved.append(package.toPackageData(groupTitle: option.title,
sourceID: option.providerID))
}
}
}
}

self.predefinedSavedPackages = allPredefinedSaved

self.customSavedPackages = response.customPackages.map {
return $0.toPackageData()
}
}

// star/unstar packages
@MainActor
func starUnstarPackage(_ packageID: String, carrierID: String) {
Expand All @@ -187,16 +177,12 @@ final class WooShippingAddPackageViewModel: ObservableObject {
}

let predefined = WooShippingPredefinedSavedOption(id: carrierID, predefinedPackageIDs: [packageID])
let createAction = WooShippingAction.createPackage(siteID: siteID, customPackage: nil, predefinedOption: predefined) { result in
switch result {
case .success(let response):
self.transformSavedPackages(response)
case .failure:
// TODO: should we undo the starring of the package if request fails?
self.starredCarriersPackages.remove(packageID)
let createAction = WooShippingAction.createPackage(siteID: siteID, customPackage: nil, predefinedOption: predefined) { [weak self] result in
if case .failure(let error) = result {
DDLogError("⛔️ Error saving Woo Shipping package: \(error)")
self?.starredCarriersPackages.remove(packageID)
}
}

stores.dispatch(createAction)
}
}
Expand Down Expand Up @@ -225,10 +211,9 @@ final class WooShippingAddPackageViewModel: ObservableObject {

// delete on backend
let deleteAction = WooShippingAction.deletePackage(siteID: siteID, packageID: packageToRemove.id) { result in
switch result {
case .success(let response):
self.transformSavedPackages(response)
case .failure:
if case .failure(let error) = result {
DDLogError("⛔️ Error removing saved Woo Shipping package: \(error)")

// undo removing of the package
// first: undo starring
if let carrierID = removedStarredCarrierID {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
observeSelectedPackage()
observeForLabelRates()
loadStoreOptions()
loadPackages()
}

/// Initialize the view model from an existing shipping label.
Expand Down Expand Up @@ -222,6 +223,20 @@ final class WooShippingCreateLabelsViewModel: ObservableObject {
}
}

// MARK: Remote
private extension WooShippingCreateLabelsViewModel {
/// Syncs packages to use for shipping label from remote.
///
func loadPackages() {
let action = WooShippingAction.loadPackages(siteID: order.siteID) { result in
if case .failure(let error) = result {
DDLogError("⛔️ Error loading packages for Woo Shipping labels: \(error)")
}
}
stores.dispatch(action)
}
}

// MARK: Utils
private extension WooShippingCreateLabelsViewModel {
/// Observes the selected package and updates the shipment weight.
Expand Down
4 changes: 4 additions & 0 deletions WooCommerce/WooCommerce.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2309,6 +2309,7 @@
CE6E110B2C91DA5D00563DD4 /* WooShippingItemRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6E110A2C91DA5D00563DD4 /* WooShippingItemRow.swift */; };
CE6E110D2C91E5FF00563DD4 /* WooShippingItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6E110C2C91E5FF00563DD4 /* WooShippingItems.swift */; };
CE6E110F2C91EF6800563DD4 /* View+RoundedBorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6E110E2C91EF6800563DD4 /* View+RoundedBorder.swift */; };
CE7269C82D11A99800D565C1 /* WooShippingAddPackageViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7269C72D11A99800D565C1 /* WooShippingAddPackageViewModelTests.swift */; };
CE7B4A582CA191FB00F764EB /* WooShippingItemRowViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7B4A572CA191F400F764EB /* WooShippingItemRowViewModelTests.swift */; };
CE7B4A5B2CA1BF9900F764EB /* WooShippingHazmat.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7B4A5A2CA1BF9900F764EB /* WooShippingHazmat.swift */; };
CE7CEC2D2C2EF0E50066FD53 /* GoogleAdsCampaignReportCardViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE7CEC2C2C2EF0E50066FD53 /* GoogleAdsCampaignReportCardViewModelTests.swift */; };
Expand Down Expand Up @@ -5428,6 +5429,7 @@
CE6E110A2C91DA5D00563DD4 /* WooShippingItemRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingItemRow.swift; sourceTree = "<group>"; };
CE6E110C2C91E5FF00563DD4 /* WooShippingItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingItems.swift; sourceTree = "<group>"; };
CE6E110E2C91EF6800563DD4 /* View+RoundedBorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+RoundedBorder.swift"; sourceTree = "<group>"; };
CE7269C72D11A99800D565C1 /* WooShippingAddPackageViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingAddPackageViewModelTests.swift; sourceTree = "<group>"; };
CE7B4A572CA191F400F764EB /* WooShippingItemRowViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingItemRowViewModelTests.swift; sourceTree = "<group>"; };
CE7B4A5A2CA1BF9900F764EB /* WooShippingHazmat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooShippingHazmat.swift; sourceTree = "<group>"; };
CE7CEC2C2C2EF0E50066FD53 /* GoogleAdsCampaignReportCardViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleAdsCampaignReportCardViewModelTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -12122,6 +12124,7 @@
CE86C8322CC8F9BB00B1764D /* WooShippingServiceCardViewModelTests.swift */,
CE315DC72CC942A200A06748 /* WooShippingServiceViewModelTests.swift */,
CE4AFE472CD239B90013C52B /* WooShippingPostPurchaseViewModelTests.swift */,
CE7269C72D11A99800D565C1 /* WooShippingAddPackageViewModelTests.swift */,
);
path = "WooShipping Create Shipping Labels";
sourceTree = "<group>";
Expand Down Expand Up @@ -17344,6 +17347,7 @@
7E7C5F8B2719AEDA00315B61 /* EditProductCategoryListViewModelTests.swift in Sources */,
0247F510286E7D26009C177E /* ProductVariationFormViewModel+ImageUploaderTests.swift in Sources */,
020B2F9123BDD71500BD79AD /* IntegerInputFormatterTests.swift in Sources */,
CE7269C82D11A99800D565C1 /* WooShippingAddPackageViewModelTests.swift in Sources */,
DECEA4492C81C1A800C28C10 /* ProductImagePickerViewModelTests.swift in Sources */,
D816DDBC22265DA300903E59 /* OrderTrackingTableViewCellTests.swift in Sources */,
579CDF01274D811D00E8903D /* StoreStatsUsageTracksEventEmitterTests.swift in Sources */,
Expand Down
Loading

0 comments on commit 5a7a18b

Please sign in to comment.