Skip to content

Commit 351ef00

Browse files
authored
Merge pull request #6603 from woocommerce/issue/6489-product-selection-ui-update
Coupons: Update product selector view buttons
2 parents 8cfe67b + ba47381 commit 351ef00

File tree

1 file changed

+123
-35
lines changed

1 file changed

+123
-35
lines changed

WooCommerce/Classes/ViewRelated/Products/ProductListSelector/ProductListSelectorViewController.swift

Lines changed: 123 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@ import Yosemite
44

55
/// Displays a paginated list of products where the user can select.
66
final class ProductListSelectorViewController: UIViewController {
7+
/// Whether the view is for selecting or excluding products
8+
private let isExclusion: Bool
9+
710
private let excludedProductIDs: [Int64]
811
private var productIDs: [Int64] = [] {
912
didSet {
1013
if productIDs != oldValue {
11-
updateNavigationTitle(productIDs: productIDs)
12-
updateNavigationRightBarButtonItem(productIDs: productIDs)
14+
updateDoneButton(productIDs: productIDs)
1315
}
1416
}
1517
}
1618

1719
private let siteID: Int64
1820
private var selectedProductIDsSubscription: AnyCancellable?
21+
private var filters: FilterProductListViewModel.Filters = FilterProductListViewModel.Filters()
1922

2023
private lazy var dataSource = ProductListMultiSelectorDataSource(siteID: siteID, excludedProductIDs: excludedProductIDs)
2124

@@ -30,14 +33,69 @@ final class ProductListSelectorViewController: UIViewController {
3033
return PaginatedListSelectorViewController(viewProperties: viewProperties, dataSource: dataSource, onDismiss: { _ in })
3134
}()
3235

36+
private lazy var contentStackView: UIStackView = {
37+
let stackView = UIStackView(arrangedSubviews: [])
38+
stackView.axis = .vertical
39+
stackView.translatesAutoresizingMaskIntoConstraints = false
40+
return stackView
41+
}()
42+
43+
private lazy var doneButton: UIButton = {
44+
let button = UIButton()
45+
button.translatesAutoresizingMaskIntoConstraints = false
46+
button.addTarget(self, action: #selector(doneButtonTapped), for: .touchUpInside)
47+
button.applyPrimaryButtonStyle()
48+
return button
49+
}()
50+
51+
private lazy var doneButtonContainer: UIView = {
52+
let buttonContainer = UIView(frame: .zero)
53+
buttonContainer.translatesAutoresizingMaskIntoConstraints = false
54+
buttonContainer.addSubview(doneButton)
55+
buttonContainer.pinSubviewToSafeArea(doneButton, insets: Constants.doneButtonInsets)
56+
return buttonContainer
57+
}()
58+
59+
private lazy var topBarContainer: UIView = {
60+
let container = UIView(frame: .zero)
61+
container.translatesAutoresizingMaskIntoConstraints = false
62+
63+
let selectAllButton = UIButton()
64+
selectAllButton.setTitle(Localization.selectAll, for: .normal)
65+
selectAllButton.translatesAutoresizingMaskIntoConstraints = false
66+
selectAllButton.addTarget(self, action: #selector(selectAllProducts), for: .touchUpInside)
67+
selectAllButton.applyLinkButtonStyle()
68+
selectAllButton.contentEdgeInsets = .zero
69+
container.addSubview(selectAllButton)
70+
71+
let filterButton = UIButton()
72+
filterButton.setTitle(Localization.filter, for: .normal)
73+
filterButton.translatesAutoresizingMaskIntoConstraints = false
74+
filterButton.addTarget(self, action: #selector(showFilter), for: .touchUpInside)
75+
filterButton.applyLinkButtonStyle()
76+
filterButton.contentEdgeInsets = .zero
77+
container.addSubview(filterButton)
78+
79+
NSLayoutConstraint.activate([
80+
container.heightAnchor.constraint(equalToConstant: Constants.topBarHeight),
81+
selectAllButton.leadingAnchor.constraint(equalTo: container.safeLeadingAnchor, constant: Constants.topBarMargin),
82+
selectAllButton.centerYAnchor.constraint(equalTo: container.centerYAnchor),
83+
container.safeTrailingAnchor.constraint(equalTo: filterButton.trailingAnchor, constant: Constants.topBarMargin),
84+
filterButton.centerYAnchor.constraint(equalTo: container.centerYAnchor),
85+
])
86+
87+
return container
88+
}()
89+
3390
// Completion callback
3491
//
3592
typealias Completion = (_ selectedProductIDs: [Int64]) -> Void
3693
private let onCompletion: Completion
3794

38-
init(excludedProductIDs: [Int64], siteID: Int64, onCompletion: @escaping Completion) {
95+
init(excludedProductIDs: [Int64], siteID: Int64, isExclusion: Bool = false, onCompletion: @escaping Completion) {
3996
self.excludedProductIDs = excludedProductIDs
4097
self.siteID = siteID
98+
self.isExclusion = isExclusion
4199
self.onCompletion = onCompletion
42100
super.init(nibName: nil, bundle: nil)
43101
}
@@ -51,12 +109,29 @@ final class ProductListSelectorViewController: UIViewController {
51109

52110
configureMainView()
53111
configureNavigation()
54-
configurePaginatedProductListSelectorChildViewController()
112+
configureContentStackView()
55113
}
56114
}
57115

58116
// MARK: - Actions
59117
private extension ProductListSelectorViewController {
118+
@objc func selectAllProducts() {
119+
// TODO
120+
}
121+
122+
@objc func showFilter() {
123+
let viewModel = FilterProductListViewModel(filters: filters, siteID: siteID)
124+
let filterProductListViewController = FilterListViewController(viewModel: viewModel, onFilterAction: { [weak self] filters in
125+
ServiceLocator.analytics.track(.productFilterListShowProductsButtonTapped, withProperties: ["filters": filters.analyticsDescription])
126+
self?.filters = filters
127+
}, onClearAction: {
128+
ServiceLocator.analytics.track(.productFilterListClearMenuButtonTapped)
129+
}, onDismissAction: {
130+
ServiceLocator.analytics.track(.productFilterListDismissButtonTapped)
131+
})
132+
present(filterProductListViewController, animated: true, completion: nil)
133+
}
134+
60135
@objc func doneButtonTapped() {
61136
completeUpdating()
62137
}
@@ -114,25 +189,13 @@ extension ProductListSelectorViewController {
114189

115190
// MARK: - UI updates
116191
private extension ProductListSelectorViewController {
117-
func updateNavigationRightBarButtonItem(productIDs: [Int64]) {
118-
if productIDs.isEmpty {
119-
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(searchButtonTapped))
120-
} else {
121-
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped))
122-
}
123-
}
124192

125-
func updateNavigationTitle(productIDs: [Int64]) {
126-
let title: String
127-
switch productIDs.count {
128-
case 0:
129-
title = Localization.titleWithoutSelectedProducts
130-
case 1:
131-
title = Localization.titleWithOneSelectedProduct
132-
default:
133-
title = String.localizedStringWithFormat(Localization.titleWithMultipleSelectedProductsFormat, productIDs.count)
134-
}
135-
navigationItem.title = title
193+
func updateDoneButton(productIDs: [Int64]) {
194+
let itemCount = String.pluralize(productIDs.count, singular: Localization.singleProduct, plural: Localization.multipleProducts)
195+
let format = isExclusion ? Localization.exclusionActionTitle : Localization.selectionActionTitle
196+
let title = String.localizedStringWithFormat(format, itemCount)
197+
doneButton.setTitle(title, for: .normal)
198+
doneButtonContainer.isHidden = productIDs.isEmpty
136199
}
137200
}
138201

@@ -144,19 +207,29 @@ private extension ProductListSelectorViewController {
144207
}
145208

146209
func configureNavigation() {
147-
updateNavigationTitle(productIDs: productIDs)
148-
updateNavigationRightBarButtonItem(productIDs: productIDs)
210+
navigationItem.title = isExclusion ? Localization.exclusionTitle : Localization.selectionTitle
211+
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(searchButtonTapped))
149212
}
150213

151-
func configurePaginatedProductListSelectorChildViewController() {
152-
observeSelectedProductIDs(observableProductIDs: dataSource.productIDs)
214+
func configureContentStackView() {
215+
contentStackView.addArrangedSubview(topBarContainer)
153216

217+
observeSelectedProductIDs(observableProductIDs: dataSource.productIDs)
154218
addChild(paginatedListSelector)
155219
paginatedListSelector.view.translatesAutoresizingMaskIntoConstraints = false
156-
view.addSubview(paginatedListSelector.view)
220+
contentStackView.addArrangedSubview(paginatedListSelector.view)
157221
paginatedListSelector.didMove(toParent: self)
158222

159-
view.pinSubviewToAllEdges(paginatedListSelector.view)
223+
contentStackView.addArrangedSubview(doneButtonContainer)
224+
doneButtonContainer.isHidden = true // Hide the button initially since no product is selected yet.
225+
226+
view.addSubview(contentStackView)
227+
NSLayoutConstraint.activate([
228+
view.leadingAnchor.constraint(equalTo: contentStackView.leadingAnchor),
229+
view.trailingAnchor.constraint(equalTo: contentStackView.trailingAnchor),
230+
view.safeTopAnchor.constraint(equalTo: contentStackView.safeTopAnchor),
231+
view.safeBottomAnchor.constraint(equalTo: contentStackView.safeBottomAnchor)
232+
])
160233
}
161234

162235
func observeSelectedProductIDs(observableProductIDs: AnyPublisher<[Int64], Never>) {
@@ -169,15 +242,30 @@ private extension ProductListSelectorViewController {
169242
// MARK: - Constants
170243
//
171244
private extension ProductListSelectorViewController {
245+
enum Constants {
246+
static let doneButtonInsets = UIEdgeInsets(top: 16, left: 16, bottom: 0, right: 16)
247+
static let topBarMargin: CGFloat = 16
248+
static let topBarHeight: CGFloat = 46
249+
}
250+
172251
enum Localization {
173252
static let noResultsPlaceholder = NSLocalizedString("No products yet",
174253
comment: "Placeholder text when there are no products on the product list selector")
175-
static let titleWithoutSelectedProducts = NSLocalizedString("Add Products", comment: "Navigation bar title for selecting multiple products.")
176-
static let titleWithOneSelectedProduct =
177-
NSLocalizedString("1 Product Selected",
178-
comment: "Navigation bar title for selecting multiple products when one product has been selected.")
179-
static let titleWithMultipleSelectedProductsFormat =
180-
NSLocalizedString("%ld Products Selected",
181-
comment: "Navigation bar title for selecting multiple products when more multiple products have been selected.")
254+
static let selectionTitle = NSLocalizedString("Select products", comment: "Title for the Select Products screen")
255+
static let exclusionTitle = NSLocalizedString("Exclude products", comment: "Title of the Exclude Products screen")
256+
static let selectionActionTitle = NSLocalizedString(
257+
"Select %1$@",
258+
comment: "Title of the action button on the Select Products screen" +
259+
"Reads like: Select 1 Product"
260+
)
261+
static let exclusionActionTitle = NSLocalizedString(
262+
"Exclude %1$@",
263+
comment: "Title of the action button on the Exclude Products screen" +
264+
"Reads like: Exclude 1 Product"
265+
)
266+
static let singleProduct = NSLocalizedString("%1$d Product", comment: "Count of one product")
267+
static let multipleProducts = NSLocalizedString("%1$d Products", comment: "Count of several products, reads like: 2 Products")
268+
static let selectAll = NSLocalizedString("Select All", comment: "Button to select all products on the product list selector")
269+
static let filter = NSLocalizedString("Filter", comment: "Button to filter products on the product list selector")
182270
}
183271
}

0 commit comments

Comments
 (0)