diff --git a/Modules/Sources/Yosemite/Model/Bookings/BookingProductFilter.swift b/Modules/Sources/Yosemite/Model/Bookings/BookingProductFilter.swift index 445473fbc63..da0d7c6f71f 100644 --- a/Modules/Sources/Yosemite/Model/Bookings/BookingProductFilter.swift +++ b/Modules/Sources/Yosemite/Model/Bookings/BookingProductFilter.swift @@ -1,20 +1,19 @@ -// periphery:ignore:all - will be used for booking filters import Foundation /// Used to filter bookings by product /// public struct BookingProductFilter: Codable, Hashable { /// ID of the product + /// periphery:ignore - to be used later when applying filter /// - public let id: Int64 + public let productID: Int64 /// Name of the product /// public let name: String - public init(id: Int64, - name: String) { - self.id = id + public init(productID: Int64, name: String) { + self.productID = productID self.name = name } } diff --git a/WooCommerce/Classes/Bookings/BookingFilters/BookableProductListSyncable.swift b/WooCommerce/Classes/Bookings/BookingFilters/BookableProductListSyncable.swift new file mode 100644 index 00000000000..d64376003bc --- /dev/null +++ b/WooCommerce/Classes/Bookings/BookingFilters/BookableProductListSyncable.swift @@ -0,0 +1,68 @@ +import Foundation +import Yosemite + +/// Syncable implementation for booking services/events (bookable product) filtering +struct BookableProductListSyncable: ListSyncable { + typealias StorageType = StorageProduct + typealias ModelType = Product + + let siteID: Int64 + + var title: String { Localization.title } + + var emptyStateMessage: String { Localization.noMembersFound } + + // MARK: - ResultsController Configuration + + func createPredicate() -> NSPredicate { + NSPredicate(format: "siteID == %lld AND productTypeKey == %@", siteID, ProductType.booking.rawValue) + } + + func createSortDescriptors() -> [NSSortDescriptor] { + [NSSortDescriptor(key: "productID", ascending: false)] + } + + // MARK: - Sync Configuration + + func createSyncAction( + pageNumber: Int, + pageSize: Int, + completion: @escaping (Result) -> Void + ) -> Action { + ProductAction.synchronizeProducts( + siteID: siteID, + pageNumber: pageNumber, + pageSize: pageSize, + stockStatus: nil, + productStatus: nil, + productType: .booking, + productCategory: nil, + sortOrder: .dateDescending, + productIDs: [], + excludedProductIDs: [], + shouldDeleteStoredProductsOnFirstPage: true, + onCompletion: completion + ) + } + + // MARK: - Display Configuration + + func displayName(for item: Product) -> String { + item.name + } +} + +private extension BookableProductListSyncable { + enum Localization { + static let title = NSLocalizedString( + "bookingServiceEventSelectorView.title", + value: "Service / Event", + comment: "Title of the booking service/event selector view" + ) + static let noMembersFound = NSLocalizedString( + "bookingServiceEventSelectorView.noMembersFound", + value: "No service or event found", + comment: "Text on the empty view of the booking service/event selector view" + ) + } +} diff --git a/WooCommerce/Classes/Bookings/BookingFilters/BookingFiltersViewModel.swift b/WooCommerce/Classes/Bookings/BookingFilters/BookingFiltersViewModel.swift index 6fefb18bb79..e786d5530a1 100644 --- a/WooCommerce/Classes/Bookings/BookingFilters/BookingFiltersViewModel.swift +++ b/WooCommerce/Classes/Bookings/BookingFilters/BookingFiltersViewModel.swift @@ -27,9 +27,9 @@ final class BookingFiltersViewModel: FilterListViewModel { filterTypeViewModels = [ teamMemberFilterViewModel, productFilterViewModel, - customerFilterViewModel, attendanceStatusFilterViewModel, paymentStatusFilterViewModel, + customerFilterViewModel, dateTimeFilterViewModel ] } @@ -188,11 +188,11 @@ extension BookingFiltersViewModel.BookingListFilter { selectedValue: filters.teamMember) case .product(let siteID): return FilterTypeViewModel(title: title, - listSelectorConfig: .products(siteID: siteID), + listSelectorConfig: .bookableProduct(siteID: siteID), selectedValue: filters.product) case .customer(let siteID): return FilterTypeViewModel(title: title, - listSelectorConfig: .customer(siteID: siteID), + listSelectorConfig: .customer(siteID: siteID, source: .booking), selectedValue: filters.customer) case .attendanceStatus: let options: [BookingAttendanceStatus?] = [nil, .booked, .checkedIn, .cancelled, .noShow] diff --git a/WooCommerce/Classes/Bookings/BookingFilters/CustomerSelector+BookingFilter.swift b/WooCommerce/Classes/Bookings/BookingFilters/CustomerSelector+BookingFilter.swift new file mode 100644 index 00000000000..4d538a6c704 --- /dev/null +++ b/WooCommerce/Classes/Bookings/BookingFilters/CustomerSelector+BookingFilter.swift @@ -0,0 +1,27 @@ +import Foundation + +extension CustomerSelectorViewController.Configuration { + static let configurationForBookingFilter = CustomerSelectorViewController.Configuration( + title: BookingFilterLocalization.customerSelectorTitle, + disallowSelectingGuest: true, + guestDisallowedMessage: BookingFilterLocalization.guestSelectionDisallowedError, + disallowCreatingCustomer: true, + showGuestLabel: true, + shouldTrackCustomerAdded: false, + isModal: false, + hideDetailText: true + ) + + enum BookingFilterLocalization { + static let customerSelectorTitle = NSLocalizedString( + "configurationForBookingFilter.customerName", + value: "Customer name", + comment: "Title for the screen to select customer in booking filtering." + ) + static let guestSelectionDisallowedError = NSLocalizedString( + "configurationForBookingFilter.guestSelectionDisallowedError", + value: "This user is a guest, and guests can’t be used for filtering bookings.", + comment: "Error message when selecting guest customer in booking filtering" + ) + } +} diff --git a/WooCommerce/Classes/Bookings/BookingFilters/SyncableListSelectorView.swift b/WooCommerce/Classes/Bookings/BookingFilters/SyncableListSelectorView.swift index 63c6a3bfdf0..23c8ccaee95 100644 --- a/WooCommerce/Classes/Bookings/BookingFilters/SyncableListSelectorView.swift +++ b/WooCommerce/Classes/Bookings/BookingFilters/SyncableListSelectorView.swift @@ -5,17 +5,18 @@ struct SyncableListSelectorView: View { @State var selectedItem: Syncable.ModelType? private let syncable: Syncable + private let initialSelection: (Syncable.ModelType?) -> Bool private let onSelection: (Syncable.ModelType?) -> Void private let viewPadding: CGFloat = 16 init(viewModel: SyncableListSelectorViewModel, syncable: Syncable, - selectedItem: Syncable.ModelType?, + initialSelection: @escaping (Syncable.ModelType?) -> Bool, onSelection: @escaping (Syncable.ModelType?) -> Void) { self.viewModel = viewModel self.syncable = syncable - self.selectedItem = selectedItem + self.initialSelection = initialSelection self.onSelection = onSelection } @@ -68,7 +69,7 @@ private extension SyncableListSelectorView { ForEach(items, id: \.self) { item in optionRow(text: syncable.displayName(for: item), - isSelected: item == selectedItem, + isSelected: isItemSelected(item), onSelection: { selectedItem = item }) } @@ -82,6 +83,13 @@ private extension SyncableListSelectorView { .background(Color(.listBackground)) } + func isItemSelected(_ item: Syncable.ModelType?) -> Bool { + if let selectedItem { + return item == selectedItem + } + return initialSelection(item) + } + func optionRow(text: String, isSelected: Bool, onSelection: @escaping () -> Void) -> some View { HStack { Text(text) diff --git a/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift b/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift index 0a907439ed3..2f3418bb03b 100644 --- a/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Filters/FilterListViewController.swift @@ -93,9 +93,11 @@ enum FilterListValueSelectorConfig { // Filter list selector for products case products(siteID: Int64) // Filter list selector for customer - case customer(siteID: Int64) + case customer(siteID: Int64, source: FilterSource) // Filter list selector for booking team member case bookingResource(siteID: Int64) + // Filter list selector for bookable product + case bookableProduct(siteID: Int64) } @@ -341,26 +343,31 @@ private extension FilterListViewController { }() self.listSelector.present(controller, animated: true) - case .customer(let siteID): + case .customer(let siteID, let source): + let configuration: CustomerSelectorViewController.Configuration = { + switch source { + case .booking: .configurationForBookingFilter + case .orders: .configurationForOrderFilter + case .products: fatalError("Customer filter not supported!") + } + }() + let selectedCustomerID = (selected.selectedValue as? CustomerFilter)?.id let controller: CustomerSelectorViewController = { return CustomerSelectorViewController( siteID: siteID, - configuration: .configurationForOrderFilter, + configuration: configuration, addressFormViewModel: nil, + selectedCustomerID: selectedCustomerID, onCustomerSelected: { [weak self] customer in selected.selectedValue = CustomerFilter(customer: customer) self?.updateUI(numberOfActiveFilters: self?.viewModel.filterTypeViewModels.numberOfActiveFilters ?? 0) self?.listSelector.reloadData() - self?.listSelector.dismiss(animated: true) } ) }() - self.listSelector.present( - WooNavigationController(rootViewController: controller), - animated: true - ) + self.listSelector.navigationController?.pushViewController(controller, animated: true) case .bookingResource(let siteID): let selectedMember = selected.selectedValue as? BookingResource let syncable = TeamMemberListSyncable(siteID: siteID) @@ -368,12 +375,31 @@ private extension FilterListViewController { let memberListSelectorView = SyncableListSelectorView( viewModel: viewModel, syncable: syncable, - selectedItem: selectedMember, + initialSelection: { $0 == selectedMember }, onSelection: { [weak self] resource in selected.selectedValue = resource self?.updateUI(numberOfActiveFilters: self?.viewModel.filterTypeViewModels.numberOfActiveFilters ?? 0) self?.listSelector.reloadData() - self?.listSelector.navigationController?.popViewController(animated: true) + } + ) + let hostingController = UIHostingController(rootView: memberListSelectorView) + listSelector.navigationController?.pushViewController(hostingController, animated: true) + + case .bookableProduct(let siteID): + let selectedProduct = selected.selectedValue as? BookingProductFilter + let syncable = BookableProductListSyncable(siteID: siteID) + let viewModel = SyncableListSelectorViewModel(syncable: syncable) + let memberListSelectorView = SyncableListSelectorView( + viewModel: viewModel, + syncable: syncable, + initialSelection: { $0?.productID == selectedProduct?.productID }, + onSelection: { [weak self] product in + selected.selectedValue = { + guard let product else { return BookingProductFilter?.none } + return BookingProductFilter(productID: product.productID, name: product.name) + }() + self?.updateUI(numberOfActiveFilters: self?.viewModel.filterTypeViewModels.numberOfActiveFilters ?? 0) + self?.listSelector.reloadData() } ) let hostingController = UIHostingController(rootView: memberListSelectorView) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSearchUICommand.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSearchUICommand.swift index 9c817ad4cd2..163924cb5e9 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSearchUICommand.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSearchUICommand.swift @@ -61,12 +61,20 @@ final class CustomerSearchUICommand: SearchUICommand { // Whether to hide button for creating customer in empty state private let disallowCreatingCustomer: Bool + // Whether to hide the detail text (username or "Guest") in each customer row + private let hideDetailText: Bool + + // The currently selected customer ID to show checkmark + private var selectedCustomerID: Int64? + init(siteID: Int64, loadResultsWhenSearchTermIsEmpty: Bool = false, showSearchFilters: Bool = false, showGuestLabel: Bool = false, shouldTrackCustomerAdded: Bool = true, disallowCreatingCustomer: Bool = false, + hideDetailText: Bool = false, + selectedCustomerID: Int64? = nil, stores: StoresManager = ServiceLocator.stores, analytics: Analytics = ServiceLocator.analytics, featureFlagService: FeatureFlagService = ServiceLocator.featureFlagService, @@ -80,6 +88,8 @@ final class CustomerSearchUICommand: SearchUICommand { self.showGuestLabel = showGuestLabel self.shouldTrackCustomerAdded = shouldTrackCustomerAdded self.disallowCreatingCustomer = disallowCreatingCustomer + self.hideDetailText = hideDetailText + self.selectedCustomerID = selectedCustomerID self.stores = stores self.analytics = analytics self.featureFlagService = featureFlagService @@ -89,6 +99,10 @@ final class CustomerSearchUICommand: SearchUICommand { self.onDidFinishSyncingAllCustomersFirstPage = onDidFinishSyncingAllCustomersFirstPage } + func updateSelectedCustomerID(_ customerID: Int64?) { + self.selectedCustomerID = customerID + } + var hideCancelButton: Bool { featureFlagService.isFeatureFlagEnabled(.betterCustomerSelectionInOrder) } @@ -143,9 +157,12 @@ final class CustomerSearchUICommand: SearchUICommand { let storageManager = ServiceLocator.storageManager let predicate = NSPredicate(format: "siteID == %lld", siteID) let newCustomerSelectorIsEnabled = featureFlagService.isFeatureFlagEnabled(.betterCustomerSelectionInOrder) - let descriptor = newCustomerSelectorIsEnabled ? - NSSortDescriptor(keyPath: \StorageCustomer.firstName, ascending: true) : NSSortDescriptor(keyPath: \StorageCustomer.customerID, ascending: false) - return ResultsController(storageManager: storageManager, matching: predicate, sortedBy: [descriptor]) + let descriptors = newCustomerSelectorIsEnabled ? + [ + NSSortDescriptor(keyPath: \StorageCustomer.firstName, ascending: true), + NSSortDescriptor(keyPath: \StorageCustomer.customerID, ascending: true) + ] : [NSSortDescriptor(keyPath: \StorageCustomer.customerID, ascending: false)] + return ResultsController(storageManager: storageManager, matching: predicate, sortedBy: descriptors) } func createStarterViewController() -> UIViewController? { @@ -171,7 +188,11 @@ final class CustomerSearchUICommand: SearchUICommand { } func createCellViewModel(model: Customer) -> UnderlineableTitleAndSubtitleAndDetailTableViewCell.ViewModel { - let detail = showGuestLabel && model.customerID == 0 ? Localization.guestLabel : model.username ?? "" + let detail: String = { + guard !hideDetailText else { return "" } + return showGuestLabel && model.customerID == 0 ? Localization.guestLabel : model.username ?? "" + }() + let isSelected = selectedCustomerID == model.customerID return CellViewModel( id: "\(model.customerID)", @@ -181,7 +202,8 @@ final class CustomerSearchUICommand: SearchUICommand { subtitle: model.email, accessibilityLabel: "", detail: detail, - underlinedText: searchTerm?.count ?? 0 > 1 ? searchTerm : "" // Only underline the search term if it's longer than 1 character + underlinedText: searchTerm?.count ?? 0 > 1 ? searchTerm : "", // Only underline the search term if it's longer than 1 character + isSelected: isSelected ) } diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSelectorViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSelectorViewController.swift index 3d5b56bf94f..7e9cb13879e 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSelectorViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/CustomerSelectorViewController.swift @@ -8,11 +8,13 @@ import Yosemite /// final class CustomerSelectorViewController: UIViewController, GhostableViewController { private var searchViewController: SearchViewController? + private var customerSearchCommand: CustomerSearchUICommand? private var emptyStateViewController: UIViewController? private let siteID: Int64 private let onCustomerSelected: (Customer) -> Void private let viewModel: CustomerSelectorViewModel private let addressFormViewModel: CreateOrderAddressFormViewModel? + private let selectedCustomerID: Int64? let configuration: CustomerSelectorViewController.Configuration @@ -35,11 +37,13 @@ final class CustomerSelectorViewController: UIViewController, GhostableViewContr /// - siteID: ID of the current site /// - configuration: UI configuration for the view controller /// - addressFormViewModel: Optional, has to be provided if the view has to include new customer creation. + /// - selectedCustomerID: Optional, ID of the currently selected customer to show checkmark /// - onCustomerSelected: Callback to be called when a customer is selected /// init(siteID: Int64, configuration: CustomerSelectorViewController.Configuration, addressFormViewModel: CreateOrderAddressFormViewModel?, + selectedCustomerID: Int64? = nil, onCustomerSelected: @escaping (Customer) -> Void) { viewModel = CustomerSelectorViewModel( siteID: siteID, @@ -48,6 +52,7 @@ final class CustomerSelectorViewController: UIViewController, GhostableViewContr self.siteID = siteID self.configuration = configuration self.addressFormViewModel = addressFormViewModel + self.selectedCustomerID = selectedCustomerID self.onCustomerSelected = onCustomerSelected super.init(nibName: nil, bundle: nil) @@ -74,6 +79,9 @@ extension CustomerSelectorViewController { // Whether guest-type customers can be selected or not var disallowSelectingGuest: Bool + // Error message when selecting guest if disallowed + var guestDisallowedMessage = Localization.guestSelectionDisallowedError + // Whether to show or hide button to create customer var disallowCreatingCustomer: Bool @@ -82,6 +90,12 @@ extension CustomerSelectorViewController { // Whether to track when a customer cell is tapped. var shouldTrackCustomerAdded: Bool + + // Whether the selector is presented modally + var isModal: Bool + + // Whether to hide the detail text (username or "Guest") in each customer row + var hideDetailText: Bool = false } } @@ -134,7 +148,9 @@ private extension CustomerSelectorViewController { func configureNavigation() { navigationItem.title = configuration.title - navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelWasPressed)) + if configuration.isModal { + navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelWasPressed)) + } if !configuration.disallowCreatingCustomer { navigationItem.rightBarButtonItem = UIBarButtonItem(image: .plusBarButtonItemImage, @@ -185,29 +201,34 @@ private extension CustomerSelectorViewController { shouldTrackCustomerAdded: Bool, disallowCreatingCustomer: Bool, onAddCustomerDetailsManually: (() -> Void)? = nil) { + let command = CustomerSearchUICommand(siteID: siteID, + loadResultsWhenSearchTermIsEmpty: loadResultsWhenSearchTermIsEmpty, + showSearchFilters: showSearchFilters, + showGuestLabel: showGuestLabel, + shouldTrackCustomerAdded: shouldTrackCustomerAdded, + disallowCreatingCustomer: disallowCreatingCustomer, + hideDetailText: configuration.hideDetailText, + selectedCustomerID: selectedCustomerID, + onAddCustomerDetailsManually: onAddCustomerDetailsManually, + onDidSelectSearchResult: onCustomerTapped, + onDidStartSyncingAllCustomersFirstPage: { + Task { @MainActor [weak self] in + guard let searchTableView = self?.searchViewController?.tableView else { + return + } + self?.displayGhostContent(over: searchTableView) + } + }, + onDidFinishSyncingAllCustomersFirstPage: { + Task { @MainActor [weak self] in + self?.removeGhostContent() + } + }) + self.customerSearchCommand = command + let searchViewController = SearchViewController( storeID: siteID, - command: CustomerSearchUICommand(siteID: siteID, - loadResultsWhenSearchTermIsEmpty: loadResultsWhenSearchTermIsEmpty, - showSearchFilters: showSearchFilters, - showGuestLabel: showGuestLabel, - shouldTrackCustomerAdded: shouldTrackCustomerAdded, - disallowCreatingCustomer: disallowCreatingCustomer, - onAddCustomerDetailsManually: onAddCustomerDetailsManually, - onDidSelectSearchResult: onCustomerTapped, - onDidStartSyncingAllCustomersFirstPage: { - Task { @MainActor [weak self] in - guard let searchTableView = self?.searchViewController?.tableView else { - return - } - self?.displayGhostContent(over: searchTableView) - } - }, - onDidFinishSyncingAllCustomersFirstPage: { - Task { @MainActor [weak self] in - self?.removeGhostContent() - } - }), + command: command, cellType: UnderlineableTitleAndSubtitleAndDetailTableViewCell.self, cellSeparator: .none ) @@ -264,13 +285,18 @@ private extension CustomerSelectorViewController { activityIndicator.startAnimating() viewModel.onCustomerSelected(customer, onCompletion: { [weak self] result in - self?.activityIndicator.stopAnimating() + guard let self else { return } + activityIndicator.stopAnimating() + customerSearchCommand?.updateSelectedCustomerID(customer.customerID) + searchViewController?.tableView.reloadData() switch result { case .success: - self?.dismiss(animated: true) + if configuration.isModal { + dismiss(animated: true) + } case .failure: - self?.showErrorNotice() + showErrorNotice() } }) } @@ -282,7 +308,7 @@ private extension CustomerSelectorViewController { func showGuestSelectionDisallowedNotice() { noticePresenter.presentingViewController = self - noticePresenter.enqueue(notice: Notice(title: Localization.guestSelectionDisallowedError, feedbackType: .error)) + noticePresenter.enqueue(notice: Notice(title: configuration.guestDisallowedMessage, feedbackType: .error)) } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/Legacy/LegacyOrderCustomerSection.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/Legacy/LegacyOrderCustomerSection.swift index 6a553b5927f..a143dc596ee 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/Legacy/LegacyOrderCustomerSection.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/Legacy/LegacyOrderCustomerSection.swift @@ -47,7 +47,8 @@ private extension CustomerSelectorViewController.Configuration { disallowSelectingGuest: false, disallowCreatingCustomer: false, showGuestLabel: false, - shouldTrackCustomerAdded: true + shouldTrackCustomerAdded: true, + isModal: true ) enum OrderCustomerLocalization { diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/OrderCustomerSection.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/OrderCustomerSection.swift index 56bbcccfe72..538f235218b 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/OrderCustomerSection.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Creation/CustomerSection/OrderCustomerSection.swift @@ -32,7 +32,8 @@ struct OrderCustomerSection: View { disallowSelectingGuest: viewModel.isCustomerAccountRequired, disallowCreatingCustomer: true, showGuestLabel: false, - shouldTrackCustomerAdded: true + shouldTrackCustomerAdded: true, + isModal: true ), addressFormViewModel: viewModel.addressFormViewModel) { customer in viewModel.addCustomerFromSearch(customer) diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/CustomerSelector+Filter.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/CustomerSelector+Filter.swift index c170579fa5c..723d55079fd 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/CustomerSelector+Filter.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/CustomerSelector+Filter.swift @@ -6,7 +6,8 @@ extension CustomerSelectorViewController.Configuration { disallowSelectingGuest: true, disallowCreatingCustomer: true, showGuestLabel: true, - shouldTrackCustomerAdded: false + shouldTrackCustomerAdded: false, + isModal: false ) enum OrderFilterLocalization { diff --git a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift index 7fb52aa0ada..35340034a70 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/Order Filters/FilterOrderListViewModel.swift @@ -265,7 +265,7 @@ extension FilterOrderListViewModel.OrderListFilter { selectedValue: filters.product) case .customer(let siteID): return FilterTypeViewModel(title: title, - listSelectorConfig: .customer(siteID: siteID), + listSelectorConfig: .customer(siteID: siteID, source: .orders), selectedValue: filters.customer) case .salesChannel: let salesChannelOptions: [SalesChannelFilter] = [.any, .pointOfSale, .webCheckout, .wpAdmin] diff --git a/WooCommerce/Classes/ViewRelated/ReusableViews/UnderlineableTitleAndSubtitleAndDetailTableViewCell.swift b/WooCommerce/Classes/ViewRelated/ReusableViews/UnderlineableTitleAndSubtitleAndDetailTableViewCell.swift index d156d0f81c2..91d0771e46c 100644 --- a/WooCommerce/Classes/ViewRelated/ReusableViews/UnderlineableTitleAndSubtitleAndDetailTableViewCell.swift +++ b/WooCommerce/Classes/ViewRelated/ReusableViews/UnderlineableTitleAndSubtitleAndDetailTableViewCell.swift @@ -13,12 +13,14 @@ final class UnderlineableTitleAndSubtitleAndDetailTableViewCell: UITableViewCell override func awakeFromNib() { super.awakeFromNib() configureBackground() + accessoryType = .none } func configureCell(searchModel: ViewModel) { accessibilityLabel = searchModel.accessibilityLabel setupTitleLabelText(with: searchModel) subtitleLabel.attributedText = subtitleAttributedString(from: searchModel) + accessoryType = searchModel.isSelected ? .checkmark : .none } override func updateConfiguration(using state: UICellConfigurationState) { @@ -42,6 +44,7 @@ extension UnderlineableTitleAndSubtitleAndDetailTableViewCell { let accessibilityLabel: String let detail: String let underlinedText: String? + let isSelected: Bool } } @@ -54,7 +57,7 @@ private extension UnderlineableTitleAndSubtitleAndDetailTableViewCell { attributes: [.font: UIFont.caption1, .foregroundColor: UIColor.textTertiary]) } - let subtitle = NSMutableAttributedString(string: viewModel.subtitle, attributes: [.font: UIFont.caption1, .foregroundColor: UIColor.text]) + let subtitle = NSMutableAttributedString(string: viewModel.subtitle, attributes: [.font: UIFont.caption1, .foregroundColor: UIColor.secondaryLabel]) if let underlinedText = viewModel.underlinedText { subtitle.underlineSubstring(underlinedText: underlinedText)