Skip to content

Commit

Permalink
Merge branch 'feature/powersearch' into develop
Browse files Browse the repository at this point in the history
Finished advanced searching page, will move to finalize the last UI elements and Error handling
  • Loading branch information
martin-headspace committed Feb 19, 2020
2 parents 6704f2c + 2e0d70c commit a72a825
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 3 deletions.
12 changes: 12 additions & 0 deletions FlinkChallenge/FlinkChallenge.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
BD6A5E7323FCEBA0003B1E4D /* Episode.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD6A5E7223FCEBA0003B1E4D /* Episode.swift */; };
BD6A5E7523FCFD98003B1E4D /* EpisodeModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD6A5E7423FCFD98003B1E4D /* EpisodeModalView.swift */; };
BD6A5E7723FD003A003B1E4D /* SearchBarUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD6A5E7623FD003A003B1E4D /* SearchBarUIView.swift */; };
BD810CEF23FDB95F00D7853A /* AdvancedFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD810CEE23FDB95F00D7853A /* AdvancedFilterView.swift */; };
BD810D3723FDD82B00D7853A /* CharacterFilteringController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD810D3623FDD82B00D7853A /* CharacterFilteringController.swift */; };
BD810D3923FDDC4200D7853A /* CharacterFilterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD810D3823FDDC4200D7853A /* CharacterFilterView.swift */; };
EB91B40C69510498EB2574BC /* Pods_FlinkChallengeTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DFA73F2EF25F32DFDB17F885 /* Pods_FlinkChallengeTests.framework */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -63,6 +66,9 @@
BD6A5E7223FCEBA0003B1E4D /* Episode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Episode.swift; sourceTree = "<group>"; };
BD6A5E7423FCFD98003B1E4D /* EpisodeModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EpisodeModalView.swift; sourceTree = "<group>"; };
BD6A5E7623FD003A003B1E4D /* SearchBarUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBarUIView.swift; sourceTree = "<group>"; };
BD810CEE23FDB95F00D7853A /* AdvancedFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdvancedFilterView.swift; sourceTree = "<group>"; };
BD810D3623FDD82B00D7853A /* CharacterFilteringController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterFilteringController.swift; sourceTree = "<group>"; };
BD810D3823FDDC4200D7853A /* CharacterFilterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterFilterView.swift; sourceTree = "<group>"; };
DFA73F2EF25F32DFDB17F885 /* Pods_FlinkChallengeTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FlinkChallengeTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -168,6 +174,8 @@
BD6A5E6D23FCBC01003B1E4D /* CharacterDetailView.swift */,
BD6A5E7423FCFD98003B1E4D /* EpisodeModalView.swift */,
BD6A5E7623FD003A003B1E4D /* SearchBarUIView.swift */,
BD810CEE23FDB95F00D7853A /* AdvancedFilterView.swift */,
BD810D3823FDDC4200D7853A /* CharacterFilterView.swift */,
);
path = Views;
sourceTree = "<group>";
Expand All @@ -177,6 +185,7 @@
children = (
BD6A5E6523FC855D003B1E4D /* CharacterFeedController.swift */,
BD6A5E7023FCEB6C003B1E4D /* EpisodeController.swift */,
BD810D3623FDD82B00D7853A /* CharacterFilteringController.swift */,
);
path = Controller;
sourceTree = "<group>";
Expand Down Expand Up @@ -359,6 +368,8 @@
buildActionMask = 2147483647;
files = (
BD6A5E6E23FCBC01003B1E4D /* CharacterDetailView.swift in Sources */,
BD810CEF23FDB95F00D7853A /* AdvancedFilterView.swift in Sources */,
BD810D3723FDD82B00D7853A /* CharacterFilteringController.swift in Sources */,
BD6A5E6C23FC9ADF003B1E4D /* CardView.swift in Sources */,
BD6A5E6923FC8F02003B1E4D /* CharacterFeedView.swift in Sources */,
BD6A5E7523FCFD98003B1E4D /* EpisodeModalView.swift in Sources */,
Expand All @@ -369,6 +380,7 @@
BD6A5E4323FC7FF7003B1E4D /* SceneDelegate.swift in Sources */,
BD6A5E6423FC823D003B1E4D /* APICharacter.swift in Sources */,
BD6A5E4523FC7FF7003B1E4D /* ContentView.swift in Sources */,
BD810D3923FDDC4200D7853A /* CharacterFilterView.swift in Sources */,
BD6A5E6623FC855D003B1E4D /* CharacterFeedController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// CharacterFilteringController.swift
// FlinkChallenge
//
// Created by Fernando Martin Garcia Del Angel on 19/02/20.
// Copyright © 2020 Fernando Martin Garcia Del Angel. All rights reserved.
//

import Foundation

class CharacterFiltering : ObservableObject, RandomAccessCollection {
typealias Element = APICharacter
@Published var characterListItems = [APICharacter]()

var startIndex: Int { characterListItems.startIndex }
var endIndex: Int { characterListItems.endIndex }
var loadStatus = LoadStatus.ready(nextPage: 1)

var baseURL = "https://rickandmortyapi.com/api/character/?"

init(name : String, status : String, species: String, type : String, gender: String){
loadFilteredCharacters(params: [name,status,species,type, gender])
}

subscript(position: Int) -> APICharacter {
return characterListItems[position]
}

func loadFilteredCharacters(params : [String]) {
var leadingQueryString : String = ""
let labels = ["name","status","species","type","gender"]
for (index, param) in params.enumerated() {
if !param.isEmpty {
leadingQueryString += "\(labels[index])=\(param.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? "")"
}

if index != params.count {
leadingQueryString += "&"
}
}
let completeURL = "\(baseURL)\(leadingQueryString)"
let url = URL(string: completeURL)!
let task = URLSession.shared.dataTask(with: url,completionHandler: parseCharactersFromResponse(data:response:error:))
task.resume()
}

func parseCharactersFromResponse(data: Data?, response : URLResponse?, error : Error?) {
guard error == nil else {
print("Error: \(error?.localizedDescription ?? "Unknown error produced")")
return
}

guard let data = data else {
print("Error: \(error?.localizedDescription ?? "Unknown error produced")")
return
}

let apiCharacters = parseCharactersFromData(data: data)
DispatchQueue.main.async {
self.characterListItems.append(contentsOf: apiCharacters)
if apiCharacters.count == 0 {
print("load status done")
} else {
print("load status unknown")
}
}
}

func parseCharactersFromData(data: Data) -> [APICharacter] {
var response : APICharactersResponse
do {
response = try JSONDecoder().decode(APICharactersResponse.self, from: data)
} catch {
print(error.localizedDescription)
return []
}

return response.results ?? []
}
}
85 changes: 85 additions & 0 deletions FlinkChallenge/FlinkChallenge/Views/AdvancedFilterView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// AdvancedFilterView.swift
// FlinkChallenge
//
// Created by Fernando Martin Garcia Del Angel on 19/02/20.
// Copyright © 2020 Fernando Martin Garcia Del Angel. All rights reserved.
//

import SwiftUI

struct RoundedButton : View {
var name : String = ""
var status : String = ""
var species : String = ""
var type: String = ""
var gender : String = ""

var body: some View {
NavigationLink(destination:
CharacterFilterView(name: name,
status: status,
species: species,
type: type,
gender: gender)) {
Button(action: {}){
HStack {
Spacer()
Text("Search")
.font(.headline)
Spacer()
}
}
.padding(.vertical, 10.0)
.padding(.horizontal, 50)
}
}
}

struct AdvancedFilterView: View {
var statuses = ["alive","dead","unknown"]
var genders = ["female","male","genderless","unknown"]
@State private var selectedStatus = 0
@State private var selectedGender = 0
@State private var name: String = ""
@State private var status: String = ""
@State private var species : String = ""
@State private var type : String = ""
@State private var gender : String = ""

var body: some View {
Form {
Section(header: Text("Basic Data")) {
TextField("Name",text: $name)
}

Section(header: Text("Other data")) {
Picker (selection: $selectedStatus, label: Text("Status")) {
ForEach(0 ..< statuses.count) {
Text(self.statuses[$0].capitalized)
}
}.pickerStyle(SegmentedPickerStyle())

Picker (selection: $selectedGender, label: Text("Gender")) {
ForEach(0 ..< genders.count) {
Text(self.genders[$0].capitalized)
}
}.pickerStyle(SegmentedPickerStyle())
TextField("Species",text: $species)
TextField("Type",text: $type)

}
RoundedButton(name: name,
status: statuses[selectedStatus],
species: species,
type: type,
gender: genders[selectedGender])
}
}
}

struct AdvancedFilterView_Previews: PreviewProvider {
static var previews: some View {
AdvancedFilterView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ struct CharacterFeedView: View {
NavigationLink(destination: CharacterDetail(character: character)) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
}
}
}
}

struct CharacterFeedView_Previews: PreviewProvider {
static var previews: some View {
Expand Down
42 changes: 42 additions & 0 deletions FlinkChallenge/FlinkChallenge/Views/CharacterFilterView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// CharacterFilterView.swift
// FlinkChallenge
//
// Created by Fernando Martin Garcia Del Angel on 19/02/20.
// Copyright © 2020 Fernando Martin Garcia Del Angel. All rights reserved.
//

import SwiftUI

struct CharacterFilterView: View {
@ObservedObject var characterFeed : CharacterFiltering
@State private var searchText : String = ""

init(name : String, status: String, species : String, type: String, gender: String) {
characterFeed = CharacterFiltering(name: name, status: status, species: species, type: type, gender: gender)
}

var body: some View {
VStack {
SearchBar(text: $searchText, placeholder: "Search for characters")
List {
ForEach(self.characterFeed.filter {
self.searchText.isEmpty ? true : $0.name!.lowercased().contains(self.searchText.lowercased())
}, id: \.id) { character in
ZStack {
Card(character: character).frame(width: 300, height: 300)
NavigationLink(destination: CharacterDetail(character: character)) {
EmptyView()
}.buttonStyle(PlainButtonStyle())
}
}
}
}.navigationBarTitle(Text("Search Results"))
}
}

struct CharacterFilterView_Previews: PreviewProvider {
static var previews: some View {
CharacterFilterView(name: "Rick", status: "", species: "", type: "", gender: "")
}
}
6 changes: 4 additions & 2 deletions FlinkChallenge/FlinkChallenge/Views/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ struct ContentView: View {
Text("Characters")
}

dummyView()
NavigationView {
AdvancedFilterView().navigationBarTitle(Text("Advanced Search"))
}
.tag(1)
.tabItem {
Text("Search")
Text("Advanced Search")
}
}
}
Expand Down

0 comments on commit a72a825

Please sign in to comment.