Skip to content

Commit

Permalink
Separate list of custom and predefined packages in view model (#14299)
Browse files Browse the repository at this point in the history
  • Loading branch information
bozidarsevo authored Nov 7, 2024
2 parents 4ef0fe0 + 12ff1f9 commit 8eb48c1
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct WooCarrierPackagesView: View {
Section {
ForEach(packageGroup.packages, id: \.id) { package in
PackageOptionView(
isSelected: selectedPackageId == package.id, // Check if this package is selected
isSelected: selectedPackageId == package.id,
package: package,
showTopDivider: false,
showType: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,61 @@ struct WooSavedPackagesSelectionView: View {
VStack(spacing: 0) {
Divider()
List {
ForEach(viewModel.packages, id: \.id) { package in
PackageOptionView(
isSelected: viewModel.selectedPackageId == package.id, // Check if this package is selected
package: package,
showTopDivider: false,
showType: true,
tapAction: {
viewModel.selectedPackageId = viewModel.selectedPackageId == package.id ? nil : package.id
}
)
.alignmentGuide(.listRowSeparatorLeading) { _ in
return 16
}
.swipeActions {
Button {
// remove package
} label: {
Image(systemName: "trash")
}
.tint(Color.withColorStudio(name: .red, shade: .shade50))
}
}
.listRowInsets(.zero)
packagesSection(for: viewModel.customPackages)
packagesSection(for: viewModel.predefinedPackages)
}
.listStyle(.plain)
Divider()
Button(WooShippingAddPackageView.Localization.addPackage) {
addPackageButtonTapped()
}
.disabled(viewModel.selectedPackageId == nil || viewModel.packages.isEmpty)
.disabled(viewModel.selectedPackageId == nil || !viewModel.hasPackages)
.buttonStyle(PrimaryButtonStyle())
.padding()
}
}

@ViewBuilder
private func packagesSection(for packages: [any WooPackageDataRepresentable]) -> some View {
if packages.isEmpty {
EmptyView()
}
else {
Section {
packagesRows(for: packages)
}
.listRowInsets(.zero)
}
}

private func packagesRows(for packages: [any WooPackageDataRepresentable]) -> some View {
ForEach(packages, id: \.id) { package in
PackageOptionView(
isSelected: viewModel.selectedPackageId == package.id,
package: package,
showTopDivider: false,
showType: true,
tapAction: {
viewModel.selectedPackageId = viewModel.selectedPackageId == package.id ? nil : package.id
}
)
.alignmentGuide(.listRowSeparatorLeading) { _ in
return 16
}
.swipeActions {
Button {
withAnimation {
viewModel.removePackage(package)
}
} label: {
Image(systemName: "trash")
}
.tint(Color.withColorStudio(name: .red, shade: .shade50))
}
}
.listRowInsets(.zero)
}

private func addPackageButtonTapped() {
// call addPackageAction with data from selected package
guard let selectedPackage = viewModel.selectedPackage else { return }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import Foundation

final class WooSavedPackagesSelectionViewModel: ObservableObject {
let packages: [any WooPackageDataRepresentable]
@Published var customPackages: [any WooPackageDataRepresentable]
@Published var predefinedPackages: [any WooPackageDataRepresentable]
@Published var selectedPackageId: UUID? = nil // Track the selected package index

init(packages: [any WooPackageDataRepresentable]) {
self.packages = packages
init(customPackages: [any WooPackageDataRepresentable],
predefinedPackages: [any WooPackageDataRepresentable]) {
self.customPackages = customPackages
self.predefinedPackages = predefinedPackages
}

var hasPackages: Bool {
return customPackages.isNotEmpty || predefinedPackages.isNotEmpty
}

var selectedPackage: WooPackageDataRepresentable? {
guard let selectedPackageId else { return nil }

let packages = customPackages + predefinedPackages

for packageItem in packages {
if selectedPackageId == packageItem.id {
return packageItem
Expand All @@ -19,4 +28,13 @@ final class WooSavedPackagesSelectionViewModel: ObservableObject {

return nil
}

func removePackage(_ packageToRemove: WooPackageDataRepresentable) {
customPackages.removeAll { package in package.id == packageToRemove.id }
predefinedPackages.removeAll { package in package.id == packageToRemove.id }

if selectedPackageId == packageToRemove.id {
selectedPackageId = nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,37 +108,38 @@ struct WooShippingAddPackageView: View {
}
}

private let savedPackagesViewModel = WooSavedPackagesSelectionViewModel(customPackages: [
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
], predefinedPackages: [
WooSavedPackageData(name: "Small Flat Rate Box",
type: "DHL Express",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "USPS Priority Mail Flat Rate Boxes",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
])

@ViewBuilder
private var savedPackageView: some View {
// TODO: dummy data for UI creation
let packages: [WooSavedPackageData] = [
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "DHL Express",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "USPS Priority Mail Flat Rate Boxes",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
]
WooSavedPackagesSelectionView(viewModel: WooSavedPackagesSelectionViewModel(packages: packages)) { packageData in
WooSavedPackagesSelectionView(viewModel: savedPackagesViewModel) { packageData in
addPackageAction(packageData)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,89 @@ import Yosemite
final class WooSavedPackagesSelectionViewModelTests: XCTestCase {
func test_it_inits_packages() {
// Given/When
let packages: [WooSavedPackageData] = testingPackages()
let viewModel = WooSavedPackagesSelectionViewModel(packages: packages)
let viewModel = WooSavedPackagesSelectionViewModel(customPackages: testingCustomPackages(),
predefinedPackages: testingPredefinedPackages())

// Then
XCTAssertEqual(viewModel.packages.count, 2)
XCTAssertEqual(viewModel.customPackages.count, 2)
XCTAssertEqual(viewModel.predefinedPackages.count, 1)
XCTAssertNil(viewModel.selectedPackageId)
XCTAssertNil(viewModel.selectedPackage)
}

func test_it_selects_package() {
// Given
let packages: [WooSavedPackageData] = testingPackages()
let viewModel = WooSavedPackagesSelectionViewModel(packages: packages)
let customPackages = testingCustomPackages()
let viewModel = WooSavedPackagesSelectionViewModel(customPackages: customPackages,
predefinedPackages: testingPredefinedPackages())

// When
viewModel.selectedPackageId = packages.first?.id
viewModel.selectedPackageId = customPackages.first?.id

// Then
XCTAssertNotNil(viewModel.selectedPackageId)
XCTAssertNotNil(viewModel.selectedPackage)
}

func test_it_removes_package() {
// Given
let customPackages = testingCustomPackages()
let customPackagesCount = customPackages.count
let viewModel = WooSavedPackagesSelectionViewModel(customPackages: customPackages,
predefinedPackages: testingPredefinedPackages())

// When
if let package = customPackages.first {
viewModel.removePackage(package)
}

// Then
XCTAssertEqual(viewModel.customPackages.count, customPackagesCount - 1)
}

func test_it_removes_selected_package() {
// Given
let customPackages = testingCustomPackages()
let customPackagesCount = customPackages.count
let viewModel = WooSavedPackagesSelectionViewModel(customPackages: customPackages,
predefinedPackages: testingPredefinedPackages())

// When
viewModel.selectedPackageId = customPackages.first?.id

// Then
XCTAssertNotNil(viewModel.selectedPackageId)
XCTAssertNotNil(viewModel.selectedPackage)

// When
if let package = customPackages.first {
viewModel.removePackage(package)
}

// Then
XCTAssertEqual(viewModel.customPackages.count, customPackagesCount - 1)
XCTAssertNil(viewModel.selectedPackageId)
XCTAssertNil(viewModel.selectedPackage)
}
}

extension WooSavedPackagesSelectionViewModelTests {
func testingPackages() -> [WooSavedPackageData] {
func testingCustomPackages() -> [WooSavedPackageData] {
return [
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg"),
WooSavedPackageData(name: "Small Flat Rate Box",
type: "Custom package",
packageType: "box",
dimensions: "21.92 × 13.67 × 4.14 cm",
weight: "5 kg")
]
}
func testingPredefinedPackages() -> [WooSavedPackageData] {
return [
WooSavedPackageData(name: "Small Flat Rate Box",
type: "DHL Express",
packageType: "box",
Expand Down

0 comments on commit 8eb48c1

Please sign in to comment.