diff --git a/Podfile b/Podfile index b1cfee6..d02c7cc 100644 --- a/Podfile +++ b/Podfile @@ -5,3 +5,4 @@ use_frameworks! pod "SwiftyJSON", ">= 2.2" pod 'Alamofire', '~> 1.2' pod 'Mixpanel' +pod 'GoogleMaps' diff --git a/adam.xcodeproj/project.pbxproj b/adam.xcodeproj/project.pbxproj index b8d7038..52ffb2e 100644 --- a/adam.xcodeproj/project.pbxproj +++ b/adam.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 21D741281B21A9A9008A8EB5 /* DiscoverView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 21D741271B21A9A9008A8EB5 /* DiscoverView.xib */; }; 21D7412A1B21AA4B008A8EB5 /* DiscoverView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21D741291B21AA4B008A8EB5 /* DiscoverView.swift */; }; 21D7412C1B21AD36008A8EB5 /* DiscoverViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21D7412B1B21AD36008A8EB5 /* DiscoverViewController.swift */; }; + 9616799B1B2C72BA00A43AD3 /* LocationSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9616799A1B2C72BA00A43AD3 /* LocationSearchViewController.swift */; }; 9656AD9F1AECC62800933A8E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9656AD9E1AECC62800933A8E /* AppDelegate.swift */; }; 9656ADA11AECC62800933A8E /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9656ADA01AECC62800933A8E /* FirstViewController.swift */; }; 9656ADA31AECC62800933A8E /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9656ADA21AECC62800933A8E /* SecondViewController.swift */; }; @@ -21,8 +22,10 @@ 9656ADA81AECC62800933A8E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9656ADA71AECC62800933A8E /* Images.xcassets */; }; 9656ADAB1AECC62800933A8E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9656ADA91AECC62800933A8E /* LaunchScreen.xib */; }; 9656ADB71AECC62900933A8E /* benriTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9656ADB61AECC62900933A8E /* benriTests.swift */; }; + 967867701B2C9A7F0047C7BB /* SearchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9678676F1B2C9A7F0047C7BB /* SearchCell.swift */; }; 969FB14E1B1AB32300439BDC /* FBSDKLoginKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 969FB14D1B1AB32300439BDC /* FBSDKLoginKit.framework */; }; 969FB1501B1AB35700439BDC /* FBSDKCoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 969FB14F1B1AB35700439BDC /* FBSDKCoreKit.framework */; }; + 96C24E901B244527006C5806 /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C24E8F1B244527006C5806 /* SearchViewController.swift */; }; 96DA5A0F1AF274670003E506 /* Const.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96DA5A0B1AF274670003E506 /* Const.swift */; }; 96DA5A101AF274670003E506 /* HorizontalPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96DA5A0C1AF274670003E506 /* HorizontalPicker.swift */; }; 96DA5A111AF274670003E506 /* LocationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96DA5A0D1AF274670003E506 /* LocationService.swift */; }; @@ -55,6 +58,7 @@ 21D741291B21AA4B008A8EB5 /* DiscoverView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiscoverView.swift; sourceTree = ""; }; 21D7412B1B21AD36008A8EB5 /* DiscoverViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DiscoverViewController.swift; sourceTree = ""; }; 5BD10A0AA37B5DD5EB928422 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + 9616799A1B2C72BA00A43AD3 /* LocationSearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationSearchViewController.swift; sourceTree = ""; }; 9656AD991AECC62800933A8E /* adam.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = adam.app; sourceTree = BUILT_PRODUCTS_DIR; }; 9656AD9D1AECC62800933A8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9656AD9E1AECC62800933A8E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -66,8 +70,10 @@ 9656ADB01AECC62900933A8E /* adamTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = adamTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 9656ADB51AECC62900933A8E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9656ADB61AECC62900933A8E /* benriTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = benriTests.swift; sourceTree = ""; }; + 9678676F1B2C9A7F0047C7BB /* SearchCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchCell.swift; sourceTree = ""; }; 969FB14D1B1AB32300439BDC /* FBSDKLoginKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FBSDKLoginKit.framework; sourceTree = ""; }; 969FB14F1B1AB35700439BDC /* FBSDKCoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = FBSDKCoreKit.framework; sourceTree = ""; }; + 96C24E8F1B244527006C5806 /* SearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = ""; }; 96DA5A0B1AF274670003E506 /* Const.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Const.swift; sourceTree = ""; }; 96DA5A0C1AF274670003E506 /* HorizontalPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalPicker.swift; sourceTree = ""; }; 96DA5A0D1AF274670003E506 /* LocationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocationService.swift; sourceTree = ""; }; @@ -152,11 +158,14 @@ 96DA5A0A1AF2744F0003E506 /* Lib */, 9656AD9E1AECC62800933A8E /* AppDelegate.swift */, 9656ADA01AECC62800933A8E /* FirstViewController.swift */, + 96C24E8F1B244527006C5806 /* SearchViewController.swift */, + 9616799A1B2C72BA00A43AD3 /* LocationSearchViewController.swift */, 9656ADA21AECC62800933A8E /* SecondViewController.swift */, 2150F5001B0EFEE200AFDF5E /* ProfileViewController.swift */, 21D7412B1B21AD36008A8EB5 /* DiscoverViewController.swift */, 21D741291B21AA4B008A8EB5 /* DiscoverView.swift */, 9656ADA41AECC62800933A8E /* Main.storyboard */, + 9678676F1B2C9A7F0047C7BB /* SearchCell.swift */, 9656ADA71AECC62800933A8E /* Images.xcassets */, 9656ADA91AECC62800933A8E /* LaunchScreen.xib */, 9656AD9C1AECC62800933A8E /* Supporting Files */, @@ -376,6 +385,7 @@ buildActionMask = 2147483647; files = ( 21AF14891B0601C800108190 /* Restaurant.swift in Sources */, + 967867701B2C9A7F0047C7BB /* SearchCell.swift in Sources */, 9656ADA31AECC62800933A8E /* SecondViewController.swift in Sources */, 96DA5A0F1AF274670003E506 /* Const.swift in Sources */, 21BF4D171B099714001CDBC3 /* RestaurantCache.swift in Sources */, @@ -388,7 +398,9 @@ 96DA5A1D1AF28AD20003E506 /* MenuServerAPI.swift in Sources */, 21D7412C1B21AD36008A8EB5 /* DiscoverViewController.swift in Sources */, 96DA5A111AF274670003E506 /* LocationService.swift in Sources */, + 9616799B1B2C72BA00A43AD3 /* LocationSearchViewController.swift in Sources */, 96DA5A121AF274670003E506 /* ImageCache.swift in Sources */, + 96C24E901B244527006C5806 /* SearchViewController.swift in Sources */, 2150F5011B0EFEE200AFDF5E /* ProfileViewController.swift in Sources */, 21AF14871B05FA0B00108190 /* RestaurantServerAPI.swift in Sources */, 9656ADA11AECC62800933A8E /* FirstViewController.swift in Sources */, diff --git a/benri/AppDelegate.swift b/benri/AppDelegate.swift index d681e11..9319aa3 100644 --- a/benri/AppDelegate.swift +++ b/benri/AppDelegate.swift @@ -7,6 +7,7 @@ // import UIKit +import Mixpanel @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -16,6 +17,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. + var mixPanelInstance:Mixpanel = Mixpanel.sharedInstanceWithToken("38c30d15d147f74c302b5162f3a2ed65") + GMSServices.provideAPIKey("AIzaSyBr0bS6ifn640dNqi9lfYk4k7YzkkSN348") + + var statusView = UIView(frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.size.width, 20)) + statusView.backgroundColor = UIColor(red: 245.0/255.0, green: 245.0/255.0, blue: 245.0/255.0, alpha: 1.0) + self.window?.rootViewController?.view.addSubview(statusView) + return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/benri/Base.lproj/Main.storyboard b/benri/Base.lproj/Main.storyboard index 9334a7d..bcb1ae5 100644 --- a/benri/Base.lproj/Main.storyboard +++ b/benri/Base.lproj/Main.storyboard @@ -18,7 +18,7 @@ - + @@ -27,7 +27,7 @@ - + @@ -39,7 +39,7 @@ - + @@ -53,14 +53,14 @@ - + - + @@ -77,16 +77,16 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -308,7 +791,7 @@ - + @@ -340,6 +823,7 @@ + @@ -362,5 +846,7 @@ + + diff --git a/benri/Bridging-Header.h b/benri/Bridging-Header.h index b23e391..ab26ced 100644 --- a/benri/Bridging-Header.h +++ b/benri/Bridging-Header.h @@ -12,6 +12,7 @@ #import #import #import +#import #endif diff --git a/benri/FirstViewController.swift b/benri/FirstViewController.swift index cfe36d4..a27c759 100644 --- a/benri/FirstViewController.swift +++ b/benri/FirstViewController.swift @@ -10,6 +10,7 @@ import UIKit import Alamofire import SwiftyJSON import CoreLocation +import Mixpanel let discoverCloseNotificationKey = "me.gobbl.adam.discoverCloseNotificationKey" let discoverSearchNotificationKey = "me.gobbl.adam.discoverSearchNotificationKey" @@ -91,7 +92,7 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll self.locationManager.requestAlwaysAuthorization() } else { isInitiated = true - self.populateMenu(true, tags: nil) + self.populateMenu(true, tags: nil, location:locationService.locationToLonLat(locationService.getCurrentLocation())) } } @@ -105,7 +106,7 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll static var onceToken : dispatch_once_t = 0 } dispatch_once(&Static.onceToken) { - self.populateMenu(false, tags: nil) + self.populateMenu(false, tags: nil, location:self.locationService.locationToLonLat(self.locationService.getCurrentLocation())) } } @@ -216,7 +217,7 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll }) } - func populateMenu(isReset:Bool, tags: String?) -> Void { + func populateMenu(isReset:Bool, tags: String?, location: [CGFloat]?) -> Void { if self.isPopulating { return } @@ -224,11 +225,13 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll self.currentLoadedIndex = 0 self.menuArray = [] } - + println("location") + println(location) isPopulating = true var menuSVAPI:MenuSVAPI = MenuSVAPI() if let searchTag = tags { menuSVAPI.getMenuByTags(searchTag, + location:location, start: self.currentLoadedIndex, limit: self.populateLength, successCallback: {(somejson) -> Void in @@ -268,7 +271,8 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll self.isPopulating = false }) } else { - menuSVAPI.getMenu(self.currentLoadedIndex, + menuSVAPI.getMenu(location, + start:self.currentLoadedIndex, limit: self.populateLength, successCallback: {(somejson) -> Void in if let json: AnyObject = somejson{ @@ -326,18 +330,43 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll } } + func castCGFloat()->(String)->CGFloat { + return { (invalue:String) -> CGFloat in + if let n = NSNumberFormatter().numberFromString(invalue) { + let result = CGFloat(n) + return result + } + return 0.0 + } + } + func scrollViewDidScroll(scrollView: UIScrollView) { if !isInitiated { return } + if scrollView.contentOffset.y + view.frame.size.height > scrollView.contentSize.height * 0.8 { - if let searchTag = const.getConst("search", key: "tag") { - self.populateMenu(false, tags: searchTag) + if let locationSearch = const.getConst("search", key: "location"){ + let location:[CGFloat] = (split(locationSearch) {$0 == ","}).map(castCGFloat()) + if let searchTag = const.getConst("search", key: "tag") { + self.populateMenu(false, tags: searchTag, location:location) + } else { + self.populateMenu(false, tags: nil, location:location) + } + } else { - self.populateMenu(false, tags: nil) + if let searchTag = const.getConst("search", key: "tag") { + self.populateMenu(false, tags: searchTag, location:nil) + } else { + self.populateMenu(false, tags: nil, location:nil) + } + } + + + } let translation = scrollView.panGestureRecognizer.translationInView(scrollView.superview!) if translation.y > 0 { @@ -371,7 +400,9 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll } }*/ cell.setImageByURL(menu.imgURL) - cell.setMenuCell(menu.menuName, retaurantName: restuarant.name, distanceVal: 1.2, pointVal: 1, price: menu.price, address: restuarant.address) + let storeDistance = self.locationService.getDistanceFrom(restuarant.location) + + cell.setMenuCell(menu.menuName, retaurantName: restuarant.name, distanceVal: storeDistance, pointVal: 1, price: menu.price, address: restuarant.address) return cell } @@ -391,26 +422,30 @@ class FirstViewController: UIViewController, CLLocationManagerDelegate, UIScroll } func updateNotificationDiscoverClose() { - // reload here - self.navigationController?.view.resignFirstResponder() - self.menuTableView.userInteractionEnabled = true - self.searchButton.enabled = true const.deleteConst("search", key: "picker") } func updateNotificationDiscoverSearch() { // Mixapanel Track - //var mixPanelInstance:Mixpanel = Mixpanel.sharedInstance() - - // reload here - self.navigationController?.view.resignFirstResponder() - self.menuTableView.userInteractionEnabled = true - self.searchButton.enabled = true - if let searchTag = const.getConst("search", key: "picker") { - //mixPanelInstance.track("Simulate Search Tag", properties: ["Tag" : searchTag]) - const.setConst("search", key: "tag", value: searchTag) - self.populateMenu(true, tags: searchTag) + if let locationSearch = const.getConst("search", key: "location"){ + let location:[CGFloat] = (split(locationSearch) {$0 == ","}).map(castCGFloat()) + if let searchTag = const.getConst("search", key: "picker") { + var mixPanelInstance:Mixpanel = Mixpanel.sharedInstance() + mixPanelInstance.track("Simulate Search Tag", properties: ["Tag" : searchTag]) + + const.setConst("search", key: "tag", value: searchTag) + self.populateMenu(true, tags: searchTag, location:location) + } + } else { + if let searchTag = const.getConst("search", key: "picker") { + var mixPanelInstance:Mixpanel = Mixpanel.sharedInstance() + mixPanelInstance.track("Simulate Search Tag", properties: ["Tag" : searchTag]) + + const.setConst("search", key: "tag", value: searchTag) + self.populateMenu(true, tags: searchTag, location:nil) + } } + const.deleteConst("search", key: "picker") } diff --git a/benri/Images.xcassets/leftArrow.imageset/Contents.json b/benri/Images.xcassets/leftArrow.imageset/Contents.json new file mode 100644 index 0000000..8b45400 --- /dev/null +++ b/benri/Images.xcassets/leftArrow.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "Left-25.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "Left-50.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "Left-100.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/benri/Images.xcassets/leftArrow.imageset/Left-100.png b/benri/Images.xcassets/leftArrow.imageset/Left-100.png new file mode 100644 index 0000000..eb71f77 Binary files /dev/null and b/benri/Images.xcassets/leftArrow.imageset/Left-100.png differ diff --git a/benri/Images.xcassets/leftArrow.imageset/Left-25.png b/benri/Images.xcassets/leftArrow.imageset/Left-25.png new file mode 100644 index 0000000..82e0d20 Binary files /dev/null and b/benri/Images.xcassets/leftArrow.imageset/Left-25.png differ diff --git a/benri/Images.xcassets/leftArrow.imageset/Left-50.png b/benri/Images.xcassets/leftArrow.imageset/Left-50.png new file mode 100644 index 0000000..bd34d39 Binary files /dev/null and b/benri/Images.xcassets/leftArrow.imageset/Left-50.png differ diff --git a/benri/Images.xcassets/rightArrow.imageset/Contents.json b/benri/Images.xcassets/rightArrow.imageset/Contents.json new file mode 100644 index 0000000..27f5b0d --- /dev/null +++ b/benri/Images.xcassets/rightArrow.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "Right-25.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "Right-50.png" + }, + { + "idiom" : "universal", + "scale" : "3x", + "filename" : "Right-100.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/benri/Images.xcassets/rightArrow.imageset/Right-100.png b/benri/Images.xcassets/rightArrow.imageset/Right-100.png new file mode 100644 index 0000000..9bbe969 Binary files /dev/null and b/benri/Images.xcassets/rightArrow.imageset/Right-100.png differ diff --git a/benri/Images.xcassets/rightArrow.imageset/Right-25.png b/benri/Images.xcassets/rightArrow.imageset/Right-25.png new file mode 100644 index 0000000..7858b0c Binary files /dev/null and b/benri/Images.xcassets/rightArrow.imageset/Right-25.png differ diff --git a/benri/Images.xcassets/rightArrow.imageset/Right-50.png b/benri/Images.xcassets/rightArrow.imageset/Right-50.png new file mode 100644 index 0000000..fe48f04 Binary files /dev/null and b/benri/Images.xcassets/rightArrow.imageset/Right-50.png differ diff --git a/benri/Info.plist b/benri/Info.plist index 588ff60..d915276 100644 --- a/benri/Info.plist +++ b/benri/Info.plist @@ -54,7 +54,7 @@ Style UIBarStyleDefault Translucent - + UISupportedInterfaceOrientations diff --git a/benri/LocationSearchViewController.swift b/benri/LocationSearchViewController.swift new file mode 100644 index 0000000..175c676 --- /dev/null +++ b/benri/LocationSearchViewController.swift @@ -0,0 +1,194 @@ +// +// LocationSearchController.swift +// adam +// +// Created by Kittikorn Ariyasuk on 6/13/15. +// Copyright (c) 2015 gobbl. All rights reserved. +// + +import Foundation + +class LocationSearchViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate { + + @IBOutlet weak var navBar: UINavigationBar! + @IBOutlet weak var searchBar: UISearchBar! + @IBOutlet weak var tableView: UITableView! + + @IBAction func cancelSearch(sender: AnyObject) { + self.selectedLocationName = "" + self.performSegueWithIdentifier("backFromSearchSegueUnwind", sender: self) + } + + private var predictData:[GMSAutocompletePrediction] = [] + private var hotSpotData:[String] = ["Current Location", "Roppongi", "Shibuya", "Ginza"] + private var hotSpotLocation:[CLLocation] = [LocationService.sharedInstance.getCurrentLocation(), + CLLocation(latitude: 35.664122, longitude: 139.729426), + CLLocation(latitude: 35.664035, longitude: 139.698212), + CLLocation(latitude: 35.672089, longitude: 139.770592)] + + private var searchActive = false + + var placesClient: GMSPlacesClient? + var selectedLocationName = "" + var selectedCoordinates = CLLocation() + + override func viewDidLoad() { + super.viewDidLoad() + + self.tableView.delegate = self + self.tableView.dataSource = self + self.searchBar.delegate = self + + placesClient = GMSPlacesClient() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } + + func searchBarTextDidBeginEditing(searchBar: UISearchBar) { + searchActive = false; + } + + func searchBarTextDidEndEditing(searchBar: UISearchBar) { + searchActive = false; + } + + func searchBarCancelButtonClicked(searchBar: UISearchBar) { + searchActive = false; + } + + func searchBarSearchButtonClicked(searchBar: UISearchBar) { + searchActive = false; + } + + func searchBar(searchBar: UISearchBar, textDidChange searchText: String) { + + let tokyo = CLLocationCoordinate2DMake(35.6833, 139.6833) + let northEast = CLLocationCoordinate2DMake(tokyo.latitude + 1, tokyo.longitude + 1) + let southWest = CLLocationCoordinate2DMake(tokyo.latitude - 1, tokyo.longitude - 1) + let bounds = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest) + let filter = GMSAutocompleteFilter() + filter.type = GMSPlacesAutocompleteTypeFilter.NoFilter + + if count(searchText) > 2 { + searchActive = true + placesClient?.autocompleteQuery(searchText, bounds: bounds, filter: filter, callback: { (results, error) -> Void in + if error != nil { + println("Autocomplete error \(error) for query '\(searchText)'") + return + } + + println("Populating results for query '\(searchText)'") + self.predictData = [GMSAutocompletePrediction]() + if let results:[GMSAutocompletePrediction] = results as? [GMSAutocompletePrediction]{ + for result in results { + self.predictData.append(result) + } + } + self.tableView.reloadData() + }) + } else { + searchActive + = false + self.predictData = [GMSAutocompletePrediction]() + self.tableView.reloadData() + } + } + + func numberOfSectionsInTableView(tableView: UITableView) -> Int { + return 1 + } + + func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + if searchActive { + return predictData.count; + } else { + return hotSpotData.count; + } + + } + + func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCellWithIdentifier("SearchCell") as! SearchCell + + if searchActive { + var regularFont = UIFont.systemFontOfSize(UIFont.labelFontSize()) + var boldFont = UIFont.boldSystemFontOfSize(UIFont.labelFontSize()) + + var bolded:NSMutableAttributedString = predictData[indexPath.row].attributedFullText as! NSMutableAttributedString + bolded.enumerateAttribute(kGMSAutocompleteMatchAttribute, inRange: NSMakeRange(0, bolded.length), options: NSAttributedStringEnumerationOptions.allZeros, usingBlock: { (value, range, stop) -> Void in + var font = (value == nil) ? regularFont : boldFont + bolded.addAttribute(NSFontAttributeName, value: font, range: range) + }) + cell.placeID = predictData[indexPath.row].placeID + self.setGeoCode(predictData[indexPath.row].placeID, cell: cell) + cell.searchText?.attributedText = bolded + } else { + cell.searchText?.text = hotSpotData[indexPath.row] + cell.coordinates = hotSpotLocation[indexPath.row] + } + + return cell; + } + + func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let footerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 27.0)) + + if searchActive { + var label = UILabel(frame: CGRectMake(0, 5, tableView.frame.size.width, 22.0)) + label.text = "powered by Google" + label.textAlignment = NSTextAlignment.Center + label.font = UIFont(name: label.font.fontName, size: 14.0) + label.alpha = 0.8 + label.textColor = UIColor(red: 247.0/255.0, green: 97.0/255.0, blue: 65.0/255.0, alpha: 1.0) + footerView.addSubview(label) + + } + return footerView + } + + func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 30.0 + } + + func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + let cell: SearchCell = self.tableView.cellForRowAtIndexPath(indexPath) as! SearchCell + + // let searchViewController = segue.destinationViewController as! searchViewController + // searchViewController.message = "Hello from the 1st View Controller" + + println("select") + println(indexPath) + selectedLocationName = cell.searchText?.text as String! + selectedCoordinates = cell.coordinates + self.performSegueWithIdentifier("selectLocationFromSearchSegueUnwind", sender: self) + + } + + private func setGeoCode(placeID:String, cell:SearchCell) -> Void { + placesClient?.lookUpPlaceID(placeID, callback: { (place, error) -> Void in + if let error = error { + println("lookup place id query error: \(error.localizedDescription)") + return + } + + if let place = place { + cell.coordinates = CLLocation(latitude: place.coordinate.latitude, longitude: place.coordinate.longitude) + + } else { + println("No place details for \(placeID)") + } + }) + } + + override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + println("prepareForSegue") + if count(selectedLocationName) > 0 { + println(selectedLocationName) + let searchViewController = segue.destinationViewController as! SearchViewController + searchViewController.searchLocation = selectedLocationName + searchViewController.searchLocationCoordinate = selectedCoordinates + } + } +} \ No newline at end of file diff --git a/benri/LocationService.swift b/benri/LocationService.swift index 65df684..abd2307 100644 --- a/benri/LocationService.swift +++ b/benri/LocationService.swift @@ -15,14 +15,18 @@ class LocationService: NSObject { private var currentLocality:String override init() { - currentLocation = CLLocation(latitude: 35.6895, longitude: 139.6917) + currentLocation = CLLocation(latitude: 35.664122, longitude: 139.729426) currentLocality = "Minato" } - func getLocation() -> CLLocation { + func getCurrentLocation() -> CLLocation { return currentLocation } + func locationToLonLat(location:CLLocation) -> [CGFloat] { + return [CGFloat(location.coordinate.longitude), CGFloat(location.coordinate.latitude)] + } + func getDistanceFrom(targetLocation:CLLocation) -> Double { return currentLocation.distanceFromLocation(targetLocation) / 1000.0 } diff --git a/benri/MenuServerAPI.swift b/benri/MenuServerAPI.swift index b04100b..3ebc18f 100644 --- a/benri/MenuServerAPI.swift +++ b/benri/MenuServerAPI.swift @@ -36,12 +36,16 @@ class MenuSVAPI { } } - func getMenu(start:Int, limit:Int, successCallback:(json:AnyObject?)->Void, errorCallback:()->Void){ + func getMenu(location:[CGFloat]?, start:Int, limit:Int, successCallback:(json:AnyObject?)->Void, errorCallback:()->Void){ - let params = [ + var params:[String:AnyObject] = [ "start": String(start), "limit": String(limit) ] + if let location = location { + params["geolocation"] = location + } + UIApplication.sharedApplication().networkActivityIndicatorVisible = true Alamofire.request(.GET, apiBaseURL + apiEndPoint, parameters: params) @@ -59,13 +63,16 @@ class MenuSVAPI { } } - func getMenuByTags(tags:String, start:Int, limit:Int, successCallback:(json:AnyObject?)->Void, errorCallback:()->Void){ + func getMenuByTags(tags:String, location:[CGFloat]?,start:Int, limit:Int, successCallback:(json:AnyObject?)->Void, errorCallback:()->Void){ - let params = [ + var params:[String:AnyObject] = [ "tags" : tags, "start": String(start), "limit": String(limit) ] + if let location = location { + params["geolocation"] = location + } UIApplication.sharedApplication().networkActivityIndicatorVisible = true Alamofire.request(.GET, apiBaseURL + apiEndPoint, parameters: params) diff --git a/benri/SearchCell.swift b/benri/SearchCell.swift new file mode 100644 index 0000000..cf9d4b7 --- /dev/null +++ b/benri/SearchCell.swift @@ -0,0 +1,33 @@ +// +// SearchCell.swift +// adam +// +// Created by Kittikorn Ariyasuk on 6/14/15. +// Copyright (c) 2015 gobbl. All rights reserved. +// + +import Foundation + +class SearchCell: UITableViewCell { + + @IBOutlet weak var searchText: UILabel! + + var placeID:String = "" + var coordinates = CLLocation() + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override func prepareForReuse() { + super.prepareForReuse() + self.searchText.text = "" + } + +} \ No newline at end of file diff --git a/benri/SearchViewController.swift b/benri/SearchViewController.swift new file mode 100644 index 0000000..fcb191b --- /dev/null +++ b/benri/SearchViewController.swift @@ -0,0 +1,176 @@ +// +// searchViewController.swift +// adam +// +// Created by Kittikorn Ariyasuk on 6/7/15. +// Copyright (c) 2015 gobbl. All rights reserved. +// + +import UIKit +import SwiftyJSON + +class SearchViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate { + + @IBOutlet weak var pickerView: UIPickerView! + @IBOutlet weak var okButton: UIButton! + @IBOutlet weak var cancelButton: UIButton! + @IBOutlet weak var surpriseButton: UIButton! + @IBOutlet weak var locationLabel: UILabel! + + @IBAction func cancelSearch(sender: AnyObject) { + NSNotificationCenter.defaultCenter().postNotificationName(discoverCloseNotificationKey, object: self) + self.dismissViewControllerAnimated(true, completion: nil) + } + @IBAction func confirmSearch(sender: AnyObject) { + NSNotificationCenter.defaultCenter().postNotificationName(discoverSearchNotificationKey, object: self) + self.dismissViewControllerAnimated(true, completion: nil) + } + + @IBAction func returnFromLocationSearchSegueActions(sender: UIStoryboardSegue){ + println("return") + println(self.searchLocation) + println(sender.identifier) + println(searchLocationCoordinate.coordinate.latitude) + if sender.identifier == "selectLocationFromSearchSegueUnwind" { + // update location + locationLabel.text = searchLocation + let lonlatSearch = String(stringInterpolationSegment: searchLocationCoordinate.coordinate.longitude) + "," + String(stringInterpolationSegment: searchLocationCoordinate.coordinate.latitude) + println(lonlatSearch) + const.setConst("search", key: "location", value: lonlatSearch) + } + } + + private let PICKER_TEXT_HEIGHT:CGFloat = 44.0 + private let PICKER_TEXT_SIZE:CGFloat = 22.0 + private let BUTTON_HEIGHT:CGFloat = 76.0 + private var activityView: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray) + + let screenSize: CGRect = UIScreen.mainScreen().bounds + var const:Const = Const.sharedInstance + var locationService:LocationService = LocationService.sharedInstance + + var placesClient: GMSPlacesClient? + private var pickerData:[String] = [] + var searchLocation:String = "" + var searchLocationCoordinate:CLLocation = LocationService.sharedInstance.getCurrentLocation() + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + placesClient = GMSPlacesClient() + + self.pickerView.delegate = self + self.pickerView.dataSource = self + + self.okButton.backgroundColor = UIColor.greenColor() + //self.okButton.frame = CGRect(x: self.okButton.frame.origin.x, y: self.okButton.frame.origin.y, width: screenSize.width/2, height: BUTTON_HEIGHT) + + self.cancelButton.backgroundColor = UIColor.redColor() + //self.cancelButton.frame = CGRect(x: self.okButton.frame.origin.x, y: self.okButton.frame.origin.y, width: screenSize.width/2, height: BUTTON_HEIGHT) + self.surpriseButton.backgroundColor = UIColor.whiteColor() + self.addBlurPage() + + self.showTags() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + private func onSuccess(json:AnyObject?) { + if let json: AnyObject = json { + let tagJSON = JSON(json) + for (index: String, itemJSON: JSON) in tagJSON["items"] { + let tag:JSON = itemJSON[0] + self.pickerData.append(tag.stringValue) + } + activityView.stopAnimating() + self.pickerView.reloadAllComponents() + } + } + + private func showTags() { + let tagSVAPI:TagSVAPI = TagSVAPI() + + activityView.center = self.view.center + activityView.startAnimating() + self.view.addSubview(activityView) + tagSVAPI.getTags(10, + successCallback: onSuccess, + errorCallback: {() -> Void in + + }) + } + + private func addBlurPage() { + self.view.backgroundColor = UIColor.clearColor() + + let blurEffect:UIBlurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark + ) + let bluredEffectView = UIVisualEffectView(effect: blurEffect) + let screenFrame = UIScreen.mainScreen().bounds + + bluredEffectView.frame = screenFrame + self.view.insertSubview(bluredEffectView, atIndex: 1) + + + let vibrancyEffect:UIVibrancyEffect = UIVibrancyEffect(forBlurEffect: blurEffect) + let vibrancyEffectView:UIVisualEffectView = UIVisualEffectView(effect: vibrancyEffect) + + vibrancyEffectView.frame = UIScreen.mainScreen().bounds//CGRect(x: screenFrame.width/2, y: 0, width: screenFrame.width/2, height: screenFrame.height) + vibrancyEffectView.setTranslatesAutoresizingMaskIntoConstraints(false) + + vibrancyEffectView.contentView.addSubview(pickerView) + // Add Vibrancy View to Blur View + bluredEffectView.contentView.insertSubview(vibrancyEffectView, atIndex: 1) + + //self.settingSwipeToSearchGesture(button) + } + + //MARK: Data Sources + func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { + return 1 + } + func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { + return pickerData.count + } + //MARK: Delegates + func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { + return pickerData[row] + } + + func pickerView(pickerView: UIPickerView, + rowHeightForComponent component: Int) -> CGFloat{ + return PICKER_TEXT_HEIGHT + } + + func pickerView(pickerView: UIPickerView, + viewForRow row: Int, + forComponent component: Int, + reusingView view: UIView!) -> UIView{ + let screenSize: CGRect = UIScreen.mainScreen().bounds + let labelWidth:CGFloat = screenSize.width + let labelHeight:CGFloat = PICKER_TEXT_HEIGHT + + var rect:CGRect = CGRectMake(0, 0, labelWidth, labelHeight) + var label:UILabel = UILabel(frame: rect) + label.text = pickerData[row] + label.font = UIFont(name: label.font.fontName, size: PICKER_TEXT_SIZE) + + label.adjustsFontSizeToFitWidth = true + label.opaque = false + label.textAlignment = NSTextAlignment.Center + label.textColor = UIColor.whiteColor() + label.clipsToBounds = false + + return label + } + + func pickerView(pickerView: UIPickerView, + didSelectRow row: Int, + inComponent component: Int){ + const.setConst("search", key: "picker", value: pickerData[row]) + + } +} \ No newline at end of file