8000 MBL-2220: Implement parent filter modal for search phase 2 by amy-at-kickstarter · Pull Request #2399 · kickstarter/ios-oss · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MBL-2220: Implement parent filter modal for search phase 2 #2399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ struct FilterCategoryView<T: FilterCategory>: View {
@StateObject var viewModel: FilterCategoryViewModel<T>

var onSelectedCategory: ((T?) -> Void)? = nil
var onResults: (() -> Void)? = nil
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buttons are moving out of FilterCategoryView and into FilterRootView, which is why I have all these deletes.

var onClose: (() -> Void)? = nil

var body: some View {
VStack(spacing: 0) {
Expand All @@ -18,11 +16,6 @@ struct FilterCategoryView<T: FilterCategory>: View {
} else {
self.categoryList
}

Spacer()

self.footerView
.padding()
}
.background(Colors.Background.surfacePrimary.swiftUIColor())

Expand All @@ -32,33 +25,6 @@ struct FilterCategoryView<T: FilterCategory>: View {
self.onSelectedCategory?(subcategory ?? category)
}
}
.onReceive(self.viewModel.seeResultsTapped) {
self.onResults?()
}
.onReceive(self.viewModel.closeTapped) {
self.onClose?()
}
}

@ViewBuilder
private var headerView: some View {
HStack {
Text(Strings.Category())
.font(Font.ksr_headingXL())
.foregroundStyle(Colors.Text.primary.swiftUIColor())
Spacer()
Button(action: { [weak viewModel] () in
viewModel?.close()
}) {
Image(ImageResource.iconCross)
.foregroundStyle(Colors.Icon.primary.swiftUIColor())
.accessibilityLabel(Strings.accessibility_discovery_buttons_close())
.accessibilityAddTraits(.isButton)
}
}
.padding(Constants.headerPadding)
.background(Colors.Background.surfacePrimary.swiftUIColor())
self.separator
}

@ViewBuilder
Expand Down Expand Up @@ -132,25 +98,6 @@ struct FilterCategoryView<T: FilterCategory>: View {
.frame(maxWidth: .infinity)
}

@ViewBuilder
private var footerView: some View {
HStack(spacing: Styles.grid(2)) {
Button(Strings.Reset_filters()) { [weak viewModel] () in
viewModel?.resetSelection()
}
.buttonStyle(KSRButtonStyleModifier(style: .outlined))
.frame(maxWidth: Constants.resetButtonMaxWidth)
.disabled(!self.viewModel.canReset)

Button(Strings.See_results()) { [weak viewModel] () in
viewModel?.seeResults()
}
.buttonStyle(KSRButtonStyleModifier(style: .filled))
.frame(maxWidth: .infinity)
.disabled(self.viewModel.isLoading)
}
}

@ViewBuilder
private func radioButton(isSelected: Bool) -> some View {
ZStack {
Expand Down Expand Up @@ -190,12 +137,6 @@ private enum Constants {
viewModel: FilterCategoryViewModel(with: ConcreteFilterCategory.allCases),
onSelectedCategory: { category in
print("Selected Category: \(category?.name ?? "None")")
},
onResults: {
print("Results tapped")
},
onClose: {
print("Closed")
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,12 @@ protocol FilterCategory: Identifiable, Equatable {
protocol FilterCategoryViewModelInputs {
associatedtype T: FilterCategory
func selectCategory(_ category: T, subcategory: T?)
func seeResults()
func close()
func resetSelection()
}

protocol FilterCategoryViewModelOutputs {
associatedtype T: FilterCategory
var selectedCategory: AnyPublisher<CategoryAndSubcategory<T>?, Never> { get }
var seeResultsTapped: AnyPublisher<Void, Never> { get }
var closeTapped: AnyPublisher<Void, Never> { get }
var categories: [T] { get }
var canReset: Bool { get }
var isLoading: Bool { get }
func isCategorySelected(_ category: T) -> Bool
func isSubcategorySelected(_ category: T?) -> Bool
Expand Down Expand Up @@ -63,7 +57,21 @@ class FilterCategoryViewModel<T: FilterCategory>: FilterCategoryViewModelType {
.assign(to: &self.$currentSubcategory)

if let category = selectedCategory {
self.selectInitialCategory(selectedCategory: category)
}
}

private func selectInitialCategory(selectedCategory: T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you initialized this page with a subcategory, it wasn't reflected in the UI. This fixes it.

if let category = self.categories.first(where: { $0 == selectedCategory }) {
self.selectCategory(category, subcategory: nil)
return
}

for category in self.categories {
if let subcategory = category.availableSubcategories?.first(where: { $0 == selectedCategory }) {
self.selectCategory(category, subcategory: subcategory)
return
}
}
}

Expand All @@ -77,31 +85,13 @@ class FilterCategoryViewModel<T: FilterCategory>: FilterCategoryViewModelType {
self.selectedCategorySubject.send(nil)
}

func seeResults() {
self.seeResultsTappedSubject.send()
}

func close() {
self.closeTappedSubject.send()
}

// MARK: - Outputs

var selectedCategory: AnyPublisher<CategoryAndSubcategory<T>?, Never> {
self.selectedCategorySubject.eraseToAnyPublisher()
}

var seeResultsTapped: AnyPublisher<Void, Never> {
self.seeResultsTappedSubject.eraseToAnyPublisher()
}

var closeTapped: AnyPublisher<Void, Never> {
self.closeTappedSubject.eraseToAnyPublisher()
}

private let selectedCategorySubject = PassthroughSubject<CategoryAndSubcategory<T>?, Never>()
private let seeResultsTappedSubject = PassthroughSubject<Void, Never>()
private let closeTappedSubject = PassthroughSubject<Void, Never>()

func isCategorySelected(_ category: T) -> Bool {
self.currentCategory?.id == category.id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,58 +33,4 @@ final class FilterCategoryViewModelTest: XCTestCase {
waitForExpectations(timeout: 0.1)
XCTAssertEqual(selectedCategory?.0, .categoryFour)
}

func testSeeResultsTapped() throws {
var cancellables: [AnyCancellable] = []

let viewModel = FilterCategoryViewModel(with: self.testCategories)
var didSeeResultsTapped = false
let expectation = expectation(description: "Waiting for see results to be tapped")
viewModel.seeResultsTapped.sink { _ in
didSeeResultsTapped = true
expectation.fulfill()
}
.store(in: &cancellables)

viewModel.seeResults()
waitForExpectations(timeout: 0.1)
XCTAssertEqual(didSeeResultsTapped, true)
}

func testCloseTapped() throws {
var cancellables: [AnyCancellable] = []

let viewModel = FilterCategoryViewModel(with: self.testCategories)
var didCloseTapped = false
let expectation = expectation(description: "Waiting for close to be tapped")
viewModel.closeTapped.sink { _ in
didCloseTapped = true
expectation.fulfill()
}
.store(in: &cancellables)

viewModel.close()
waitForExpectations(timeout: 0.1)
XCTAssertEqual(didCloseTapped, true)
}

func testReset() throws {
var cancellables: [AnyCancellable] = []

let viewModel = FilterCategoryViewModel(with: self.testCategories)

var selectedCategory: (ConcreteFilterCategory, subcategory: ConcreteFilterCategory?)? = nil
let expectation = expectation(description: "Waiting for reset")
expectation.expectedFulfillmentCount = 2
viewModel.selectedCategory.sink { selection in
selectedCategory = selection
expectation.fulfill()
}
.store(in: &cancellables)

viewModel.selectCategory(.categoryFour)
viewModel.resetSelection()
waitForExpectations(timeout: 0.1)
XCTAssertNil(selectedCategory)
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
0