Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import Yosemite
import SwiftUI

/// Displays a single collapsible shipment item row or grouped parent and child shipment item rows
struct CollapsibleShipmentCard: View {
struct CollapsibleShipmentItemCard: View {
@State private var isCollapsed: Bool = true

private let viewModel: CollapsibleShipmentCardViewModel
private let viewModel: CollapsibleShipmentItemCardViewModel

init(viewModel: CollapsibleShipmentCardViewModel) {
init(viewModel: CollapsibleShipmentItemCardViewModel) {
self.viewModel = viewModel
}

Expand All @@ -22,15 +22,15 @@ struct CollapsibleShipmentCard: View {

if !isCollapsed {
VStack(spacing: 0) {
ForEach(Array(viewModel.childShipmentRows.enumerated()), id: \.element.id) { index, item in
ForEach(Array(viewModel.childItemRows.enumerated()), id: \.element.id) { index, item in
VStack(spacing: 0) {
Divider()

SelectableShipmentRow(viewModel: item)
SelectableShipmentItemRow(viewModel: item)
.padding(.leading, Layout.horizontalPadding * 2)
.padding(.trailing, Layout.horizontalPadding)
.padding(.vertical, Layout.verticalPadding)
.background(backgroundForChildShipmentRow(isFinalRow: index == viewModel.childShipmentRows.count - 1))
.background(backgroundForChildShipmentRow(isFinalRow: index == viewModel.childItemRows.count - 1))
}
}
}
Expand All @@ -41,19 +41,19 @@ struct CollapsibleShipmentCard: View {
}
}

private extension CollapsibleShipmentCard {
private extension CollapsibleShipmentItemCard {
@ViewBuilder
var mainShipmentRow: some View {
if viewModel.childShipmentRows.isEmpty {
SelectableShipmentRow(viewModel: viewModel.mainShipmentRow)
if viewModel.childItemRows.isEmpty {
SelectableShipmentItemRow(viewModel: viewModel.mainItemRow)
} else {
Button(action: {
withAnimation {
isCollapsed.toggle()
}
}, label: {
ZStack(alignment: .topTrailing) {
SelectableShipmentRow(viewModel: viewModel.mainShipmentRow)
SelectableShipmentItemRow(viewModel: viewModel.mainItemRow)
.contentShape(Rectangle())

Image(uiImage: isCollapsed ? .chevronDownImage : .chevronUpImage)
Expand Down Expand Up @@ -86,7 +86,7 @@ private extension CollapsibleShipmentCard {
}
}

private extension CollapsibleShipmentCard {
private extension CollapsibleShipmentItemCard {
enum Layout {
static let borderCornerRadius: CGFloat = 8
static let borderWidth: CGFloat = 0.5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,30 @@ import SwiftUI
import WooFoundation
import Yosemite

/// View model for `CollapsibleShipmentCard`.
final class CollapsibleShipmentCardViewModel: ObservableObject, Identifiable {
/// View model for `CollapsibleShipmentItemCard`.
final class CollapsibleShipmentItemCardViewModel: ObservableObject, Identifiable {
let id = UUID()

/// The main shipment row.
let mainShipmentRow: SelectableShipmentRowViewModel
/// The main item row.
let mainItemRow: SelectableShipmentItemRowViewModel

/// Child shipment rows, if the shipment has more than one quantity
let childShipmentRows: [SelectableShipmentRowViewModel]
let childItemRows: [SelectableShipmentItemRowViewModel]

var onSelectionChange: (() -> Void)?

var selectedShipmentIds: [String] {
if mainShipmentRow.selected {
if childShipmentRows.isNotEmpty {
return childShipmentRows.map { $0.shipmentId }
var selectedItemIds: [String] {
if mainItemRow.selected {
if childItemRows.isNotEmpty {
return childItemRows.map { $0.itemID }
} else {
return [mainShipmentRow.shipmentId]
return [mainItemRow.itemID]
}
}

return childShipmentRows
return childItemRows
.filter { $0.selected }
.map(\.shipmentId)
.map(\.itemID)
}

init(parentShipmentId: String,
Expand All @@ -37,41 +37,41 @@ final class CollapsibleShipmentCardViewModel: ObservableObject, Identifiable {
let childShippingItem = WooShippingItemRowViewModel(item: ShippingLabelPackageItem(copy: item, quantity: 1.0),
currency: currency)

self.mainShipmentRow = SelectableShipmentRowViewModel(shipmentId: parentShipmentId,
self.mainItemRow = SelectableShipmentItemRowViewModel(itemID: parentShipmentId,
isSelectable: true,
item: mainShippingItem,
showQuantity: true)
self.childShipmentRows = childShipmentIds.map({
SelectableShipmentRowViewModel(shipmentId: $0,
isSelectable: true,
item: childShippingItem,
showQuantity: false)
self.childItemRows = childShipmentIds.map({
SelectableShipmentItemRowViewModel(itemID: $0,
isSelectable: true,
item: childShippingItem,
showQuantity: false)
})

observeSelection()
}

func selectAll() {
mainShipmentRow.setSelected(true)
childShipmentRows.forEach({ $0.setSelected(true) })
mainItemRow.setSelected(true)
childItemRows.forEach({ $0.setSelected(true) })
onSelectionChange?()
}
}

private extension CollapsibleShipmentCardViewModel {
private extension CollapsibleShipmentItemCardViewModel {
func observeSelection() {
mainShipmentRow.onSelectedChange = { [weak self] row in
mainItemRow.onSelectedChange = { [weak self] row in
guard let self else { return }

childShipmentRows.forEach({ $0.setSelected(row.selected) })
childItemRows.forEach({ $0.setSelected(row.selected) })
onSelectionChange?()
}

childShipmentRows.forEach({
childItemRows.forEach({
$0.onSelectedChange = { [weak self] row in
guard let self else { return }

mainShipmentRow.setSelected(false)
mainItemRow.setSelected(false)
onSelectionChange?()
}
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import Yosemite
import SwiftUI

/// Row for a selectable shipment item to ship with the Woo Shipping extension.
struct SelectableShipmentRow: View {
@ObservedObject private var viewModel: SelectableShipmentRowViewModel
struct SelectableShipmentItemRow: View {
@ObservedObject private var viewModel: SelectableShipmentItemRowViewModel

init(viewModel: SelectableShipmentRowViewModel) {
init(viewModel: SelectableShipmentItemRowViewModel) {
self.viewModel = viewModel
}

Expand Down Expand Up @@ -53,7 +53,7 @@ struct SelectableShipmentRow: View {
}
}

private extension SelectableShipmentRow {
private extension SelectableShipmentItemRow {
@ViewBuilder
func selectionCircle(selected: Bool) -> some View {
if selected {
Expand All @@ -75,7 +75,7 @@ private extension SelectableShipmentRow {
}
}

private extension SelectableShipmentRow {
private extension SelectableShipmentItemRow {
enum Layout {
static let horizontalSpacing: CGFloat = 16
static let imageSize: CGFloat = 56.0
Expand All @@ -85,12 +85,12 @@ private extension SelectableShipmentRow {
}

#Preview {
SelectableShipmentRow(viewModel: SelectableShipmentRowViewModel(shipmentId: "123",
isSelectable: false,
item: WooShippingItemRowViewModel(imageUrl: nil,
quantityLabel: "3",
name: "Little Nap Brazil 250g",
detailsLabel: "15×10×8cm • Espresso",
weightLabel: "275g",
priceLabel: "$60.00")))
SelectableShipmentItemRow(viewModel: SelectableShipmentItemRowViewModel(itemID: "123",
isSelectable: false,
item: WooShippingItemRowViewModel(imageUrl: nil,
quantityLabel: "3",
name: "Little Nap Brazil 250g",
detailsLabel: "15×10×8cm • Espresso",
weightLabel: "275g",
priceLabel: "$60.00")))
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import WooFoundation
import Yosemite

/// View model for `SelectableShipmentRow`.
final class SelectableShipmentRowViewModel: ObservableObject, Identifiable {
final class SelectableShipmentItemRowViewModel: ObservableObject, Identifiable {
let id = UUID()

let item: WooShippingItemRowViewModel
Expand All @@ -12,17 +12,17 @@ final class SelectableShipmentRowViewModel: ObservableObject, Identifiable {

let isSelectable: Bool

let shipmentId: String
let itemID: String

let showQuantity: Bool

var onSelectedChange: ((SelectableShipmentRowViewModel) -> Void)?
var onSelectedChange: ((SelectableShipmentItemRowViewModel) -> Void)?

init(shipmentId: String,
init(itemID: String,
isSelectable: Bool,
item: WooShippingItemRowViewModel,
showQuantity: Bool = true) {
self.shipmentId = shipmentId
self.itemID = itemID
self.isSelectable = isSelectable
self.item = item
self.showQuantity = showQuantity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ struct WooShippingSplitShipmentsDetailView: View {

VStack(spacing: Layout.verticalSpacing) {
ForEach(viewModel.shipmentCardViewModels) { item in
CollapsibleShipmentCard(viewModel: item)
CollapsibleShipmentItemCard(viewModel: item)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject {
"\(itemsWeightLabel) • \(itemsPriceLabel)"
}

let shipmentCardViewModels: [CollapsibleShipmentCardViewModel]
let shipmentCardViewModels: [CollapsibleShipmentItemCardViewModel]

@Published private(set) var moveToNoticeViewModel: MoveToShipmentNoticeViewModel?

Expand All @@ -48,7 +48,7 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject {
self.shippingSettingsService = shippingSettingsService

self.shipmentCardViewModels = {
var viewModels = [CollapsibleShipmentCardViewModel]()
var viewModels = [CollapsibleShipmentItemCardViewModel]()
for item in items {
// TODO: #15303 Set IDs based on web logic
let childShipmentIds: [String] = {
Expand All @@ -64,10 +64,10 @@ final class WooShippingSplitShipmentsViewModel: ObservableObject {
return children
}()

let viewModel = CollapsibleShipmentCardViewModel(parentShipmentId: "\(item.productOrVariationID)",
childShipmentIds: childShipmentIds,
item: item,
currency: order.currency)
let viewModel = CollapsibleShipmentItemCardViewModel(parentShipmentId: "\(item.productOrVariationID)",
childShipmentIds: childShipmentIds,
item: item,
currency: order.currency)
viewModels.append(viewModel)
}
return viewModels
Expand Down Expand Up @@ -111,7 +111,7 @@ private extension WooShippingSplitShipmentsViewModel {

func showMoveToNotice() {
let selectedItemsCount = {
shipmentCardViewModels.map { $0.selectedShipmentIds.count }.reduce(0, +)
shipmentCardViewModels.map { $0.selectedItemIds.count }.reduce(0, +)
}()

guard selectedItemsCount > 0 else {
Expand Down
Loading