Skip to content

Commit 7071b45

Browse files
authored
Merge pull request #7713 from woocommerce/pairing/20220902-common-protocol-for-country
Orders Details: Use common class for Country and State selector in Order Details
2 parents 618b3a0 + 4caaa7c commit 7071b45

File tree

8 files changed

+92
-156
lines changed

8 files changed

+92
-156
lines changed

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/AddressFormViewModelProtocol.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,19 +345,19 @@ open class AddressFormViewModel: ObservableObject {
345345
/// Creates a view model to be used when selecting a country for primary fields
346346
///
347347
func createCountryViewModel() -> CountrySelectorViewModel {
348-
let selectedCountryBinding = Binding(
348+
let selectedCountryBinding = Binding<AreaSelectorCommandProtocol?>(
349349
get: { self.fields.selectedCountry },
350-
set: { self.fields.selectedCountry = $0 }
350+
set: { self.fields.selectedCountry = $0 as? Country}
351351
)
352352
return CountrySelectorViewModel(countries: allCountries, selected: selectedCountryBinding)
353353
}
354354

355355
/// Creates a view model to be used when selecting a state for primary fields
356356
///
357357
func createStateViewModel() -> StateSelectorViewModel {
358-
let selectedStateBinding = Binding(
358+
let selectedStateBinding = Binding<AreaSelectorCommandProtocol?>(
359359
get: { self.fields.selectedState },
360-
set: { self.fields.selectedState = $0 }
360+
set: { self.fields.selectedState = $0 as? StateOfACountry}
361361
)
362362

363363
// Sort states from the selected country
@@ -368,19 +368,19 @@ open class AddressFormViewModel: ObservableObject {
368368
/// Creates a view model to be used when selecting a country for secondary fields
369369
///
370370
func createSecondaryCountryViewModel() -> CountrySelectorViewModel {
371-
let selectedCountryBinding = Binding(
371+
let selectedCountryBinding = Binding<AreaSelectorCommandProtocol?>(
372372
get: { self.secondaryFields.selectedCountry },
373-
set: { self.secondaryFields.selectedCountry = $0 }
373+
set: { self.secondaryFields.selectedCountry = $0 as? Country}
374374
)
375375
return CountrySelectorViewModel(countries: allCountries, selected: selectedCountryBinding)
376376
}
377377

378378
/// Creates a view model to be used when selecting a state for secondary fields
379379
///
380380
func createSecondaryStateViewModel() -> StateSelectorViewModel {
381-
let selectedStateBinding = Binding(
381+
let selectedStateBinding = Binding<AreaSelectorCommandProtocol?>(
382382
get: { self.secondaryFields.selectedState },
383-
set: { self.secondaryFields.selectedState = $0 }
383+
set: { self.secondaryFields.selectedState = $0 as? StateOfACountry}
384384
)
385385

386386
// Sort states from the selected country
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import Foundation
2+
import Yosemite
3+
import SwiftUI
4+
5+
protocol AreaSelectorCommandProtocol {
6+
var name: String { get }
7+
var code: String { get }
8+
}
9+
10+
extension Country: AreaSelectorCommandProtocol {}
11+
extension StateOfACountry: AreaSelectorCommandProtocol {}
12+
13+
final class AreaSelectorCommand: ObservableListSelectorCommand {
14+
/// Original array of areas
15+
///
16+
private let areas: [AreaSelectorCommandProtocol]
17+
18+
/// Data to display
19+
///
20+
@Published private(set) var data: [AreaSelectorCommandProtocol]
21+
22+
/// Current selected area
23+
///
24+
@Binding private(set) var selected: AreaSelectorCommandProtocol?
25+
26+
/// Navigation bar title
27+
///
28+
var navigationBarTitle: String? = ""
29+
30+
init(areas: [AreaSelectorCommandProtocol], selected: Binding<AreaSelectorCommandProtocol?>) {
31+
self.areas = areas
32+
self.data = areas
33+
self._selected = selected
34+
}
35+
36+
func handleSelectedChange(selected: AreaSelectorCommandProtocol, viewController: ViewController) {
37+
self.selected = selected
38+
viewController.navigationController?.popViewController(animated: true)
39+
}
40+
41+
func isSelected(model: AreaSelectorCommandProtocol) -> Bool {
42+
(model.code == selected?.code) && (model.name == selected?.name)
43+
}
44+
45+
func configureCell(cell: BasicTableViewCell, model: AreaSelectorCommandProtocol) {
46+
cell.textLabel?.text = model.name
47+
}
48+
49+
/// Filter available areas that contains a given search term.
50+
///
51+
func filterAreas(term: String) {
52+
guard term.isNotEmpty else {
53+
return data = areas
54+
}
55+
56+
// Trim the search term to remove newlines or whitespaces (e.g added from the keyboard predictive text) from both ends
57+
data = areas.filter { $0.name.localizedCaseInsensitiveContains(term.trim()) }
58+
}
59+
}

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/CountrySelectorCommand.swift

Lines changed: 0 additions & 55 deletions
This file was deleted.

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/CountrySelectorViewModel.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@ import Yosemite
55
/// View Model for the `CountrySelector` view.
66
///
77
final class CountrySelectorViewModel: FilterListSelectorViewModelable, ObservableObject {
8-
98
/// Current search term entered by the user.
109
/// Each update will trigger an update to the `command` that contains the country data.
1110
var searchTerm: String = "" {
1211
didSet {
13-
command.filterCountries(term: searchTerm)
12+
command.filterAreas(term: searchTerm)
1413
}
1514
}
1615

1716
/// Command that powers the `ListSelector` view.
1817
///
19-
let command: CountrySelectorCommand
18+
let command: AreaSelectorCommand
2019

2120
/// Navigation title
2221
///
@@ -26,8 +25,8 @@ final class CountrySelectorViewModel: FilterListSelectorViewModelable, Observabl
2625
///
2726
let filterPlaceholder = Localization.placeholder
2827

29-
init(countries: [Country], selected: Binding<Country?>) {
30-
self.command = CountrySelectorCommand(countries: countries, selected: selected)
28+
init(countries: [Country], selected: Binding<AreaSelectorCommandProtocol?>) {
29+
self.command = AreaSelectorCommand( areas: countries, selected: selected)
3130
}
3231
}
3332

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/StateSelectorCommand.swift

Lines changed: 0 additions & 55 deletions
This file was deleted.

WooCommerce/Classes/ViewRelated/Orders/Order Details/Address Edit/StateSelectorViewModel.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ final class StateSelectorViewModel: FilterListSelectorViewModelable, ObservableO
1010
/// Each update will trigger an update to the `command` that contains the state data.
1111
var searchTerm: String = "" {
1212
didSet {
13-
command.filterStates(term: searchTerm)
13+
command.filterAreas(term: searchTerm)
1414
}
1515
}
1616

1717
/// Command that powers the `ListSelector` view.
1818
///
19-
let command: StateSelectorCommand
19+
let command: AreaSelectorCommand
2020

2121
/// Navigation title
2222
///
@@ -26,8 +26,8 @@ final class StateSelectorViewModel: FilterListSelectorViewModelable, ObservableO
2626
///
2727
let filterPlaceholder = Localization.placeholder
2828

29-
init(states: [StateOfACountry], selected: Binding<StateOfACountry?>) {
30-
self.command = StateSelectorCommand(states: states, selected: selected)
29+
init(states: [StateOfACountry], selected: Binding<AreaSelectorCommandProtocol?>) {
30+
self.command = AreaSelectorCommand(areas: states, selected: selected)
3131
}
3232
}
3333

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@
594594
265C99E628B9CB8E005E6117 /* StoreInfoViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 265C99E528B9CB8E005E6117 /* StoreInfoViewModifiers.swift */; };
595595
265D909D2446688C00D66F0F /* ProductCategoryViewModelBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 267CFE1824435A5500AF3A13 /* ProductCategoryViewModelBuilderTests.swift */; };
596596
2662D90626E1571900E25611 /* ListSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662D90526E1571900E25611 /* ListSelector.swift */; };
597-
2662D90826E15D6E00E25611 /* CountrySelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662D90726E15D6E00E25611 /* CountrySelectorCommand.swift */; };
597+
2662D90826E15D6E00E25611 /* AreaSelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662D90726E15D6E00E25611 /* AreaSelectorCommand.swift */; };
598598
2662D90A26E16B3600E25611 /* FilterListSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662D90926E16B3600E25611 /* FilterListSelector.swift */; };
599599
2664210126F3E1BB001FC5B4 /* ModalHostingPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2664210026F3E1BB001FC5B4 /* ModalHostingPresentationController.swift */; };
600600
2664210326F40FB1001FC5B4 /* View+ScrollModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2664210226F40FB1001FC5B4 /* View+ScrollModifiers.swift */; };
@@ -651,7 +651,6 @@
651651
26C6E8E026E2B7BD00C7BB0F /* CountrySelectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8DF26E2B7BD00C7BB0F /* CountrySelectorViewModel.swift */; };
652652
26C6E8E426E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E326E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift */; };
653653
26C6E8E626E6B5F500C7BB0F /* StateSelectorViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E526E6B5F500C7BB0F /* StateSelectorViewModel.swift */; };
654-
26C6E8E826E6B6AC00C7BB0F /* StateSelectorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E726E6B6AC00C7BB0F /* StateSelectorCommand.swift */; };
655654
26C6E8EA26E8FD3900C7BB0F /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8E926E8FD3900C7BB0F /* LazyView.swift */; };
656655
26C6E8EC26E8FF4800C7BB0F /* LazyNavigationLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */; };
657656
26CCBE0B2523B3650073F94D /* RefundProductsTotalTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26CCBE0A2523B3650073F94D /* RefundProductsTotalTableViewCell.swift */; };
@@ -2616,7 +2615,7 @@
26162615
265C99E328B9C834005E6117 /* StoreInfoProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreInfoProvider.swift; sourceTree = "<group>"; };
26172616
265C99E528B9CB8E005E6117 /* StoreInfoViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreInfoViewModifiers.swift; sourceTree = "<group>"; };
26182617
2662D90526E1571900E25611 /* ListSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSelector.swift; sourceTree = "<group>"; };
2619-
2662D90726E15D6E00E25611 /* CountrySelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountrySelectorCommand.swift; sourceTree = "<group>"; };
2618+
2662D90726E15D6E00E25611 /* AreaSelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AreaSelectorCommand.swift; sourceTree = "<group>"; };
26202619
2662D90926E16B3600E25611 /* FilterListSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilterListSelector.swift; sourceTree = "<group>"; };
26212620
2664210026F3E1BB001FC5B4 /* ModalHostingPresentationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalHostingPresentationController.swift; sourceTree = "<group>"; };
26222621
2664210226F40FB1001FC5B4 /* View+ScrollModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+ScrollModifiers.swift"; sourceTree = "<group>"; };
@@ -2672,7 +2671,6 @@
26722671
26C6E8DF26E2B7BD00C7BB0F /* CountrySelectorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountrySelectorViewModel.swift; sourceTree = "<group>"; };
26732672
26C6E8E326E2D87C00C7BB0F /* CountrySelectorViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountrySelectorViewModelTests.swift; sourceTree = "<group>"; };
26742673
26C6E8E526E6B5F500C7BB0F /* StateSelectorViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateSelectorViewModel.swift; sourceTree = "<group>"; };
2675-
26C6E8E726E6B6AC00C7BB0F /* StateSelectorCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateSelectorCommand.swift; sourceTree = "<group>"; };
26762674
26C6E8E926E8FD3900C7BB0F /* LazyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = "<group>"; };
26772675
26C6E8EB26E8FF4800C7BB0F /* LazyNavigationLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LazyNavigationLink.swift; sourceTree = "<group>"; };
26782676
26CCBE0A2523B3650073F94D /* RefundProductsTotalTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefundProductsTotalTableViewCell.swift; sourceTree = "<group>"; };
@@ -6884,9 +6882,8 @@
68846882
AEC95D402774C5AE001571F5 /* AddressFormViewModelProtocol.swift */,
68856883
AEE2610E26E664CE00B142A0 /* EditOrderAddressFormViewModel.swift */,
68866884
2662D90926E16B3600E25611 /* FilterListSelector.swift */,
6887-
2662D90726E15D6E00E25611 /* CountrySelectorCommand.swift */,
6885+
2662D90726E15D6E00E25611 /* AreaSelectorCommand.swift */,
68886886
26C6E8DF26E2B7BD00C7BB0F /* CountrySelectorViewModel.swift */,
6889-
26C6E8E726E6B6AC00C7BB0F /* StateSelectorCommand.swift */,
68906887
26C6E8E526E6B5F500C7BB0F /* StateSelectorViewModel.swift */,
68916888
);
68926889
path = "Address Edit";
@@ -10314,7 +10311,7 @@
1031410311
D831E2DC230E0558000037D0 /* Authentication.swift in Sources */,
1031510312
26DB7E3528636D2200506173 /* NonEditableOrderBanner.swift in Sources */,
1031610313
314DC4BF268D183600444C9E /* CardReaderSettingsKnownReaderStorage.swift in Sources */,
10317-
2662D90826E15D6E00E25611 /* CountrySelectorCommand.swift in Sources */,
10314+
2662D90826E15D6E00E25611 /* AreaSelectorCommand.swift in Sources */,
1031810315
02393069291A065000B2632F /* DomainRowView.swift in Sources */,
1031910316
024A543422BA6F8F00F4F38E /* DeveloperEmailChecker.swift in Sources */,
1032010317
02AB407C27827C9100929CF3 /* ChartPlaceholderView.swift in Sources */,
@@ -10575,7 +10572,6 @@
1057510572
579CDEFF274D7E7900E8903D /* StoreStatsUsageTracksEventEmitter.swift in Sources */,
1057610573
74F9E9CE214C036400A3F2D2 /* NoPeriodDataTableViewCell.swift in Sources */,
1057710574
314DC4BD268D158F00444C9E /* CardReaderSettingsKnownReadersProvider.swift in Sources */,
10578-
26C6E8E826E6B6AC00C7BB0F /* StateSelectorCommand.swift in Sources */,
1057910575
576EA39225264C7400AFC0B3 /* RefundConfirmationViewController.swift in Sources */,
1058010576
2688641B25D3202B00821BA5 /* EditAttributesViewController.swift in Sources */,
1058110577
B50911302049E27A007D25DC /* DashboardViewController.swift in Sources */,

0 commit comments

Comments
 (0)