Filtering search results
This commit is contained in:
parent
9733495593
commit
579495053c
@ -30,9 +30,11 @@
|
||||
7A11474723FF2AA500B424AF /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474623FF2AA500B424AF /* User.swift */; };
|
||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
|
||||
7A11474B23FF368B00B424AF /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474A23FF368B00B424AF /* Settings.swift */; };
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADC6249D43210035F39E /* RegionsController.swift */; };
|
||||
7A33381124990DAE00D878F1 /* FiltersController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A33381024990DAE00D878F1 /* FiltersController.swift */; };
|
||||
7A333814249A532400D878F1 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A333813249A532400D878F1 /* Filter.swift */; };
|
||||
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AA24360DC800E59687 /* Dated.swift */; };
|
||||
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AC2436350B00E59687 /* SearchController.swift */; };
|
||||
7A3F07AF24366DF900E59687 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A3F07AE24366DF900E59687 /* Filter.swift */; };
|
||||
7A43F9F8246C8A6200BA5B49 /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A43F9F7246C8A6200BA5B49 /* JWT.swift */; };
|
||||
7A530B78240010D900CBFE6E /* InputMask in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B77240010D900CBFE6E /* InputMask */; };
|
||||
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
|
||||
@ -66,6 +68,7 @@
|
||||
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A96AE2E246B2BCD00297C33 /* WebKit.framework */; };
|
||||
7A96AE31246B2FE400297C33 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
|
||||
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
|
||||
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.swift */; };
|
||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8B2435C38700258F61 /* CustomTextField.swift */; };
|
||||
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB67E8D2435D1A000258F61 /* CustomButton.swift */; };
|
||||
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.swift */; };
|
||||
@ -92,9 +95,11 @@
|
||||
7A11474823FF2B2D00B424AF /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
|
||||
7A11474A23FF368B00B424AF /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
||||
7A27ADC6249D43210035F39E /* RegionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegionsController.swift; sourceTree = "<group>"; };
|
||||
7A33381024990DAE00D878F1 /* FiltersController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FiltersController.swift; sourceTree = "<group>"; };
|
||||
7A333813249A532400D878F1 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = "<group>"; };
|
||||
7A3F07AA24360DC800E59687 /* Dated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dated.swift; sourceTree = "<group>"; };
|
||||
7A3F07AC2436350B00E59687 /* SearchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchController.swift; sourceTree = "<group>"; };
|
||||
7A3F07AE24366DF900E59687 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = "<group>"; };
|
||||
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
|
||||
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
|
||||
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
|
||||
@ -126,6 +131,7 @@
|
||||
7A96AE2E246B2BCD00297C33 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
7A96AE30246B2FE400297C33 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
7A96AE32246C095700297C33 /* Base64FS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base64FS.swift; sourceTree = "<group>"; };
|
||||
7AB562B9249C9E9B00473D53 /* Region.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Region.swift; sourceTree = "<group>"; };
|
||||
7AB67E8B2435C38700258F61 /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = "<group>"; };
|
||||
7AB67E8D2435D1A000258F61 /* CustomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButton.swift; sourceTree = "<group>"; };
|
||||
7AEFE727240455E200910EB7 /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
|
||||
@ -211,6 +217,8 @@
|
||||
7A3F07AC2436350B00E59687 /* SearchController.swift */,
|
||||
7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */,
|
||||
7A6E03272485951700DB22ED /* OwnersController.swift */,
|
||||
7A33381024990DAE00D878F1 /* FiltersController.swift */,
|
||||
7A27ADC6249D43210035F39E /* RegionsController.swift */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
@ -245,7 +253,8 @@
|
||||
7A530B7F2401803A00CBFE6E /* Vehicle.swift */,
|
||||
7A0516192414FF0900FC55AC /* DateSection.swift */,
|
||||
7A6DD90D24337930009DE740 /* PlateNumber.swift */,
|
||||
7A3F07AE24366DF900E59687 /* Filter.swift */,
|
||||
7A333813249A532400D878F1 /* Filter.swift */,
|
||||
7AB562B9249C9E9B00473D53 /* Region.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@ -439,12 +448,14 @@
|
||||
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
|
||||
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */,
|
||||
7A3F07AD2436350B00E59687 /* SearchController.swift in Sources */,
|
||||
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */,
|
||||
7A6DD90C24335A6D009DE740 /* FlagLayer.swift in Sources */,
|
||||
7AB67E8C2435C38700258F61 /* CustomTextField.swift in Sources */,
|
||||
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */,
|
||||
7A6DD90E24337930009DE740 /* PlateNumber.swift in Sources */,
|
||||
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */,
|
||||
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */,
|
||||
7A33381124990DAE00D878F1 /* FiltersController.swift in Sources */,
|
||||
7A11474923FF2B2D00B424AF /* Response.swift in Sources */,
|
||||
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */,
|
||||
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
|
||||
@ -467,10 +478,11 @@
|
||||
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
|
||||
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
|
||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */,
|
||||
7A27ADC7249D43210035F39E /* RegionsController.swift in Sources */,
|
||||
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
|
||||
7A333814249A532400D878F1 /* Filter.swift in Sources */,
|
||||
7A11474B23FF368B00B424AF /* Settings.swift in Sources */,
|
||||
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
|
||||
7A3F07AF24366DF900E59687 /* Filter.swift in Sources */,
|
||||
7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */,
|
||||
7A64AE812469E16100ABE48E /* ProgressAnimatedView.swift in Sources */,
|
||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
|
||||
@ -619,7 +631,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 15;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@ -641,7 +653,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 15;
|
||||
CURRENT_PROJECT_VERSION = 16;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
|
||||
@ -223,14 +223,14 @@
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="VehicleCell" id="VEP-QD-i6y" customClass="VehicleCell" customModule="AutoCat" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="85"/>
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="85.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VEP-QD-i6y" id="8hH-8I-XLB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="85"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="85.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Kia (JF) Optima" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AQY-7N-q8D">
|
||||
<rect key="frame" x="8" y="8" width="124" height="21"/>
|
||||
<rect key="frame" x="8" y="8" width="124" height="21.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -242,7 +242,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cvf-vM-QnT" customClass="PlateView" customModule="AutoCat" customModuleProvider="target">
|
||||
<rect key="frame" x="8" y="37" width="317" height="40"/>
|
||||
<rect key="frame" x="8" y="37.5" width="317" height="40"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="40" id="Xoz-Iw-PCU"/>
|
||||
@ -280,15 +280,92 @@
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="6Uh-9i-MKR"/>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="kEp-Rw-7hu"/>
|
||||
<navigationItem key="navigationItem" id="kEp-Rw-7hu">
|
||||
<barButtonItem key="backBarButtonItem" title="Back" id="7QQ-Qi-qEw"/>
|
||||
<barButtonItem key="rightBarButtonItem" image="line.horizontal.3.decrease" catalog="system" id="mvq-Q5-tVc">
|
||||
<connections>
|
||||
<action selector="onFilter:" destination="UPf-uT-oOr" id="z2g-n9-tJ0"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="tableView" destination="dB3-iP-QRo" id="b3n-R9-6lI"/>
|
||||
<segue destination="xtc-Md-WHl" kind="show" id="XGo-Dt-MEf"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="xsk-7S-rvc" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4200.8000000000002" y="142.57871064467767"/>
|
||||
</scene>
|
||||
<!--Filters-->
|
||||
<scene sceneID="guf-tR-b25">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="FiltersController" id="xtc-Md-WHl" customClass="FiltersController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="ACq-OO-MJ9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="tol-Qd-fB2"/>
|
||||
</view>
|
||||
<toolbarItems/>
|
||||
<navigationItem key="navigationItem" title="Filters" id="U4X-4i-ZJm">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="z1q-3D-LSC">
|
||||
<connections>
|
||||
<action selector="onDone:" destination="xtc-Md-WHl" id="SaN-2o-frs"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<segue destination="mwd-dq-ihi" kind="show" id="n3A-4T-cFK"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="bdg-V0-dfn" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4940" y="144"/>
|
||||
</scene>
|
||||
<!--Regions Controller-->
|
||||
<scene sceneID="Aej-R9-1fN">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="RegionsController" hidesBottomBarWhenPushed="YES" id="mwd-dq-ihi" customClass="RegionsController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="d0c-Nb-ZHe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" allowsMultipleSelection="YES" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="zEt-R6-oSY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="mwd-dq-ihi" id="q6l-kV-3Og"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="zEt-R6-oSY" firstAttribute="leading" secondItem="d0c-Nb-ZHe" secondAttribute="leading" id="muf-Z6-ce5"/>
|
||||
<constraint firstItem="zEt-R6-oSY" firstAttribute="top" secondItem="d0c-Nb-ZHe" secondAttribute="top" id="qkW-ZF-ZjV"/>
|
||||
<constraint firstAttribute="bottom" secondItem="zEt-R6-oSY" secondAttribute="bottom" id="vHZ-rp-tcD"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zEt-R6-oSY" secondAttribute="trailing" id="x0p-bT-D5f"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="TQH-W9-FD9"/>
|
||||
</view>
|
||||
<toolbarItems/>
|
||||
<navigationItem key="navigationItem" id="bUY-8e-NfY">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="w1V-C0-NZn">
|
||||
<connections>
|
||||
<action selector="onDone:" destination="mwd-dq-ihi" id="DbN-Ih-WZH"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
|
||||
<connections>
|
||||
<outlet property="tableView" destination="zEt-R6-oSY" id="UPW-kx-wwM"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="p1i-aS-QZU" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5688.8000000000002" y="142.57871064467767"/>
|
||||
</scene>
|
||||
<!--Settings-->
|
||||
<scene sceneID="G47-o0-Caa">
|
||||
<objects>
|
||||
@ -634,6 +711,7 @@
|
||||
<image name="eye" catalog="system" width="128" height="81"/>
|
||||
<image name="eye.fill" catalog="system" width="128" height="78"/>
|
||||
<image name="gear" catalog="system" width="128" height="119"/>
|
||||
<image name="line.horizontal.3.decrease" catalog="system" width="128" height="73"/>
|
||||
<image name="magnifyingglass" catalog="system" width="128" height="115"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
123
AutoCat/Controllers/FiltersController.swift
Normal file
123
AutoCat/Controllers/FiltersController.swift
Normal file
@ -0,0 +1,123 @@
|
||||
import UIKit
|
||||
import Eureka
|
||||
import RxSwift
|
||||
|
||||
class FiltersController: FormViewController {
|
||||
|
||||
var done = false
|
||||
var filter: Filter!
|
||||
var onDone: (() -> Void)?
|
||||
var regions: [Region] = []
|
||||
|
||||
let bag = DisposeBag()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
form +++ Section("Main filters") { $0.tag = "MainFilters" }
|
||||
<<< PushRow<String>("Brand") { row in
|
||||
row.title = "Brand"
|
||||
row.value = self.filter.brand ?? "Any"
|
||||
row.selectorTitle = "Brands"
|
||||
row.optionsProvider = .lazy({ form, completion in
|
||||
Api.getBrands().observeOn(MainScheduler.instance).subscribe(onNext: { brands in
|
||||
completion(["Any"] + brands)
|
||||
}, onError: { error in
|
||||
print("Get brands error: ", error)
|
||||
}).disposed(by: self.bag)
|
||||
})
|
||||
}.onPresent(removeSectionName(from:to:))
|
||||
.onChange { self.filter.brand = $0.value == "Any" ? nil : $0.value }
|
||||
.cellUpdate { $1.value = self.filter.brand ?? "Any" }
|
||||
|
||||
<<< PushRow<String>("Model") { row in
|
||||
row.title = "Model"
|
||||
row.value = self.filter.model ?? "Any"
|
||||
row.disabled = "$Brand == 'Any'"
|
||||
row.optionsProvider = .lazy({ form, completion in
|
||||
guard let brand = self.filter.brand else {
|
||||
completion(["Any"])
|
||||
return
|
||||
}
|
||||
Api.getModels(of: brand).observeOn(MainScheduler.instance).subscribe(onNext: { models in
|
||||
completion(["Any"] + models)
|
||||
}, onError: { error in
|
||||
print("Get models error: ", error)
|
||||
}).disposed(by: self.bag)
|
||||
})
|
||||
}.onPresent(removeSectionName(from:to:))
|
||||
.onChange { self.filter.model = $0.value == "Any" ? nil : $0.value }
|
||||
.cellUpdate { $1.value = self.filter.model ?? "Any" }
|
||||
|
||||
<<< PushRow<String>("Color") { row in
|
||||
row.title = "Color"
|
||||
row.value = self.filter.color ?? "Any"
|
||||
row.optionsProvider = .lazy({ form, completion in
|
||||
Api.getColors().observeOn(MainScheduler.instance).subscribe(onNext: { colors in
|
||||
completion(["Any"] + colors)
|
||||
}, onError: { error in
|
||||
print("Get colors error: ", error)
|
||||
}).disposed(by: self.bag)
|
||||
})
|
||||
}.onPresent(removeSectionName(from:to:))
|
||||
.onChange { self.filter.color = $0.value == "Any" ? nil : $0.value }
|
||||
.cellUpdate { $1.value = self.filter.color ?? "Any" }
|
||||
|
||||
form +++ Section() { $0.tag = "Regions" }
|
||||
<<< LabelRow("RegionsRow") { row in
|
||||
row.title = "Regions"
|
||||
row.value = self.filter.regions?.map(String.init).joined(separator: ",") ?? "Any"
|
||||
row.cellUpdate { cell, _ in
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
}
|
||||
}
|
||||
.onCellSelection { cell, row in
|
||||
let sb = UIStoryboard(name: "Main", bundle: nil)
|
||||
let vc = sb.instantiateViewController(identifier: "RegionsController") as RegionsController
|
||||
vc.regionCodes = self.filter.regions ?? []
|
||||
vc.onDone = { regions in
|
||||
row.value = regions?.map(String.init).joined(separator: ",") ?? "Any"
|
||||
self.filter.regions = regions
|
||||
}
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
form +++ Section()
|
||||
<<< ButtonRow("ClearAll") { $0.title = "Clear all filters" }.onCellSelection { cell, row in
|
||||
self.filter.clear()
|
||||
if let section = self.form.sectionBy(tag: "MainFilters") {
|
||||
// For some reason certain cells do not redraw after first reload
|
||||
section.reload()
|
||||
section.reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.done = false
|
||||
}
|
||||
|
||||
// override func viewDidDisappear(_ animated: Bool) {
|
||||
// super.viewDidDisappear(animated)
|
||||
// if self.done {
|
||||
// self.onDone?()
|
||||
// }
|
||||
// }
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
if self.done {
|
||||
self.onDone?()
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func onDone(_ sender: UIBarButtonItem) {
|
||||
self.done = true
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
func removeSectionName(from: FormViewController, to: SelectorViewController<SelectorRow<PushSelectorCell<String>>>) {
|
||||
to.sectionKeyForValue = { _ in "" }
|
||||
}
|
||||
}
|
||||
128
AutoCat/Controllers/RegionsController.swift
Normal file
128
AutoCat/Controllers/RegionsController.swift
Normal file
@ -0,0 +1,128 @@
|
||||
import UIKit
|
||||
import RxSwift
|
||||
|
||||
class RegionsDataSourse: UITableViewDiffableDataSource<Region, Int> {
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return snapshot().sectionIdentifiers[section].name
|
||||
}
|
||||
}
|
||||
|
||||
class RegionsController: UIViewController, UISearchResultsUpdating, UITableViewDelegate {
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
var regions: [Region] = []
|
||||
var regionsFiltered: [Region] = []
|
||||
var done = false
|
||||
var onDone: (([Int]?) -> Void)?
|
||||
var regionCodes: [Int] = []
|
||||
var datasource: RegionsDataSourse!
|
||||
|
||||
let searchController = UISearchController(searchResultsController: nil)
|
||||
let bag = DisposeBag()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
searchController.searchResultsUpdater = self
|
||||
searchController.obscuresBackgroundDuringPresentation = false
|
||||
searchController.searchBar.placeholder = "Search regions"
|
||||
navigationItem.searchController = searchController
|
||||
navigationItem.hidesSearchBarWhenScrolling = false
|
||||
definesPresentationContext = true
|
||||
|
||||
self.datasource = RegionsDataSourse(tableView: self.tableView) { tableView, indexPath, code -> UITableViewCell? in
|
||||
var cell = tableView.dequeueReusableCell(withIdentifier: "RegionCell")
|
||||
if cell == nil {
|
||||
cell = UITableViewCell(style: .value1, reuseIdentifier: "RegionCell")
|
||||
}
|
||||
|
||||
let selectedIndexPaths = tableView.indexPathsForSelectedRows
|
||||
let rowIsSelected = selectedIndexPaths != nil && selectedIndexPaths!.contains(indexPath)
|
||||
cell?.accessoryType = rowIsSelected ? .checkmark : .none
|
||||
cell?.selectionStyle = .none
|
||||
|
||||
cell?.textLabel?.text = String(code)
|
||||
return cell
|
||||
}
|
||||
|
||||
Api.getRegions().observeOn(MainScheduler.instance).subscribe(onNext: { regions in
|
||||
self.regions = regions
|
||||
self.regionsFiltered = regions
|
||||
self.updateTableView()
|
||||
self.applySelection()
|
||||
}, onError: { error in
|
||||
print("Get regions error: ", error)
|
||||
}).disposed(by: self.bag)
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
if self.done {
|
||||
self.onDone?(self.regionCodes)
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func onDone(_ sender: UIBarButtonItem) {
|
||||
self.done = true
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
func updateTableView() {
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Region, Int>()
|
||||
snapshot.appendSections(self.regionsFiltered)
|
||||
for region in self.regionsFiltered {
|
||||
snapshot.appendItems(region.codes, toSection: region)
|
||||
}
|
||||
self.datasource.apply(snapshot);
|
||||
}
|
||||
|
||||
func applySelection() {
|
||||
self.regionCodes.forEach { code in
|
||||
if let section = self.regionsFiltered.firstIndex(where: { $0.codes.contains(code) }) {
|
||||
if let row = self.regionsFiltered[section].codes.firstIndex(of: code) {
|
||||
let indexPath = IndexPath(row: row, section: section)
|
||||
self.tableView.selectRow(at: indexPath, animated: false, scrollPosition: .middle)
|
||||
let cell = tableView.cellForRow(at: indexPath)!
|
||||
cell.accessoryType = .checkmark
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDelegate
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)!
|
||||
cell.accessoryType = .checkmark
|
||||
|
||||
if let codeStr = cell.textLabel?.text, let code = Int(codeStr) {
|
||||
if !self.regionCodes.contains(code) {
|
||||
self.regionCodes.append(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)!
|
||||
cell.accessoryType = .none
|
||||
|
||||
if let codeStr = cell.textLabel?.text, let code = Int(codeStr) {
|
||||
self.regionCodes.removeAll(where: { $0 == code })
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UISearchResultsUpdating
|
||||
|
||||
func updateSearchResults(for searchController: UISearchController) {
|
||||
let newQuery = searchController.searchBar.text?.uppercased() ?? ""
|
||||
|
||||
if newQuery.isEmpty {
|
||||
self.regionsFiltered = self.regions
|
||||
} else {
|
||||
self.regionsFiltered = self.regions.filter { $0.name.lowercased().contains(newQuery.lowercased()) }
|
||||
}
|
||||
self.updateTableView()
|
||||
self.applySelection()
|
||||
}
|
||||
}
|
||||
@ -81,4 +81,17 @@ class SearchController: UIViewController, UISearchResultsUpdating {
|
||||
self.filter.searchString = newQuery
|
||||
self.filterRelay.accept(self.filter)
|
||||
}
|
||||
|
||||
// MARK: -
|
||||
|
||||
@IBAction func onFilter(_ sender: UIBarButtonItem) {
|
||||
let sb = UIStoryboard(name: "Main", bundle: nil)
|
||||
let controller = sb.instantiateViewController(identifier: "FiltersController") as FiltersController
|
||||
controller.filter = self.filter
|
||||
controller.onDone = {
|
||||
self.filter = controller.filter
|
||||
self.filterRelay.accept(self.filter)
|
||||
}
|
||||
self.navigationController?.pushViewController(controller, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,4 +2,34 @@ import Foundation
|
||||
|
||||
struct Filter {
|
||||
var searchString = ""
|
||||
var brand: String?
|
||||
var model: String?
|
||||
var color: String?
|
||||
var regions: [Int]?
|
||||
|
||||
mutating func clear() {
|
||||
self.brand = nil
|
||||
self.model = nil
|
||||
self.color = nil
|
||||
self.regions = nil
|
||||
}
|
||||
|
||||
func queryDictionary() -> [String: String] {
|
||||
var dict: [String: String] = ["query": self.searchString]
|
||||
|
||||
if let brand = self.brand {
|
||||
dict["brand"] = brand
|
||||
}
|
||||
if let model = self.model {
|
||||
dict["model"] = model
|
||||
}
|
||||
if let color = self.color {
|
||||
dict["color"] = color
|
||||
}
|
||||
if let regions = self.regions {
|
||||
dict["regions"] = regions.map(String.init).joined(separator: ",")
|
||||
}
|
||||
|
||||
return dict
|
||||
}
|
||||
}
|
||||
|
||||
10
AutoCat/Models/Region.swift
Normal file
10
AutoCat/Models/Region.swift
Normal file
@ -0,0 +1,10 @@
|
||||
import Foundation
|
||||
|
||||
struct Region: Codable, Hashable {
|
||||
var name: String
|
||||
var codes: [Int]
|
||||
|
||||
static func == (lhs: Region, rhs: Region) -> Bool {
|
||||
return lhs.name == rhs.name
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ class Api {
|
||||
return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
|
||||
}
|
||||
|
||||
private static func createRequest<T>(api: String, method: String, body: [String: T]? = nil) -> URLRequest? where T: LosslessStringConvertible {
|
||||
private static func createRequest(api: String, method: String, body: [String: String]? = nil) -> URLRequest? {
|
||||
guard var urlComponents = URLComponents(string: Constants.baseUrl + api) else { return nil }
|
||||
|
||||
if let body = body, method.uppercased() == "GET" {
|
||||
@ -26,7 +26,7 @@ class Api {
|
||||
return request
|
||||
}
|
||||
|
||||
private static func makeRequest<T, U>(api: String, method: String, body: [String: U]? = nil) -> Observable<T> where T: Decodable, U: LosslessStringConvertible {
|
||||
private static func makeRequest<T>(api: String, method: String = "GET", body: [String: String]? = nil) -> Observable<T> where T: Decodable {
|
||||
guard let request = self.createRequest(api: api, method: method, body: body) else {
|
||||
return Observable.error(self.genError("Error creating request", suggestion: ""))
|
||||
}
|
||||
@ -100,11 +100,7 @@ class Api {
|
||||
}
|
||||
|
||||
public static func getVehicles(with filter: Filter) -> Observable<[Vehicle]> {
|
||||
let body = [
|
||||
"limit": "0", // Unlimited
|
||||
"query": filter.searchString
|
||||
]
|
||||
return self.makeRequest(api: "vehicles", method: "GET", body: body)
|
||||
return self.makeRequest(api: "vehicles", method: "GET", body: filter.queryDictionary())
|
||||
}
|
||||
|
||||
public static func checkVehicle(by number: String, force: Bool = false) -> Observable<Vehicle> {
|
||||
@ -122,4 +118,20 @@ class Api {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func getBrands() -> Observable<[String]> {
|
||||
return self.makeRequest(api: "vehicles/brands")
|
||||
}
|
||||
|
||||
public static func getModels(of brand: String) -> Observable<[String]> {
|
||||
return self.makeRequest(api: "vehicles/models", body: ["brand": brand])
|
||||
}
|
||||
|
||||
public static func getColors() -> Observable<[String]> {
|
||||
return self.makeRequest(api: "vehicles/colors")
|
||||
}
|
||||
|
||||
public static func getRegions() -> Observable<[Region]> {
|
||||
return self.makeRequest(api: "vehicles/regions")
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ import Foundation
|
||||
enum Constants {
|
||||
static var baseUrl: String {
|
||||
#if DEBUG
|
||||
//return "http://127.0.0.1:3000/"
|
||||
return "https://vps.aliencat.pro:8443/"
|
||||
return "http://127.0.0.1:3000/"
|
||||
//return "https://vps.aliencat.pro:8443/"
|
||||
#else
|
||||
return "https://vps.aliencat.pro:8443/"
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user