diff --git a/README.md b/README.md index 100678d..8d0049b 100644 --- a/README.md +++ b/README.md @@ -1,83 +1,17 @@ -### Basic Yelp client +Overview: Build a Yelp search app. -This is a headless example of how to implement an OAuth 1.0a Yelp API client. The Yelp API provides an application token that allows applications to make unauthenticated requests to their search API. +Time taken: 15 hrs. -### Next steps +User stories done: -- Check out `MainViewController.m` to see how to use the `YelpClient`. -- Augment the search method in the `YelpClient` with whatever search parameters you want to support. +Search results page +- Custom cells should have the proper Auto Layout constraints +- Search bar should be in the navigation bar (doesn't have to expand to show location like the real Yelp app does). -### Sample request +Filter page. Unfortunately, not all the filters are supported in the Yelp API. +- The filters you should actually have are: category, sort (best match, distance, highest rated), radius (meters), deals (on/off). +- The filters table should be organized into sections as in the mock. +- Categories should show a subset of the full list with a "See All" row to expand. - I show all. +- adding a line here for comment -``` -self.client = [[YelpClient alloc] initWithConsumerKey:kYelpConsumerKey consumerSecret:kYelpConsumerSecret accessToken:kYelpToken accessSecret:kYelpTokenSecret]; - -[self.client searchWithTerm:@"Thai" success:^(AFHTTPRequestOperation *operation, id response) { - NSLog(@"response: %@", response); -} failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"error: %@", [error description]); -}]; -``` - -### Sample response - -``` -businesses = ( - { - categories = ( - ( - Thai, - thai - ) - ); - "display_phone" = "+1-415-931-6917"; - id = "lers-ros-thai-san-francisco"; - "image_url" = "http://s3-media2.ak.yelpcdn.com/bphoto/IStxUNVdfuPR2ddDAIPk_A/ms.jpg"; - "is_claimed" = 1; - "is_closed" = 0; - location = { - address = ( - "730 Larkin St" - ); - city = "San Francisco"; - "country_code" = US; - "cross_streets" = "Olive St & Ellis St"; - "display_address" = ( - "730 Larkin St", - "(b/t Olive St & Ellis St)", - Tenderloin, - "San Francisco, CA 94109" - ); - neighborhoods = ( - Tenderloin - ); - "postal_code" = 94109; - "state_code" = CA; - }; - "menu_date_updated" = 1387658025; - "menu_provider" = "single_platform"; - "mobile_url" = "http://m.yelp.com/biz/lers-ros-thai-san-francisco"; - name = "Lers Ros Thai"; - phone = 4159316917; - rating = 4; - "rating_img_url" = "http://s3-media4.ak.yelpcdn.com/assets/2/www/img/c2f3dd9799a5/ico/stars/v1/stars_4.png"; - "rating_img_url_large" = "http://s3-media2.ak.yelpcdn.com/assets/2/www/img/ccf2b76faa2c/ico/stars/v1/stars_large_4.png"; - "rating_img_url_small" = "http://s3-media4.ak.yelpcdn.com/assets/2/www/img/f62a5be2f902/ico/stars/v1/stars_small_4.png"; - "review_count" = 1154; - "snippet_image_url" = "http://s3-media4.ak.yelpcdn.com/photo/D40HpcJt-O6Ll654S_--6w/ms.jpg"; - "snippet_text" = "Fantastic pad-see-ew. Super rich, flavorful sauce and plenty of ginormous prawns, especially for a $12 price tag in San Francisco. I went through a pretty..."; - url = "http://www.yelp.com/biz/lers-ros-thai-san-francisco"; - } - ); - region = { - center = { - latitude = "37.7703124"; - longitude = "-122.43647245575"; - }; - span = { - "latitude_delta" = "0.06424638000000016"; - "longitude_delta" = "0.07145348265001417"; - }; - }; - total = 760; -``` +![Yelp](yelp.gif) diff --git a/Yelp.xcodeproj/project.pbxproj b/Yelp.xcodeproj/project.pbxproj index 54f5e66..88e99a9 100644 --- a/Yelp.xcodeproj/project.pbxproj +++ b/Yelp.xcodeproj/project.pbxproj @@ -22,6 +22,10 @@ 42FD6C6618DC286B000BF2B9 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42FD6C4E18DC286B000BF2B9 /* UIKit.framework */; }; 42FD6C6E18DC286B000BF2B9 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 42FD6C6C18DC286B000BF2B9 /* InfoPlist.strings */; }; 42FD6C7018DC286B000BF2B9 /* YelpTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 42FD6C6F18DC286B000BF2B9 /* YelpTests.m */; }; + 48EF1B671956ACF800882BCD /* ReviewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 48EF1B651956ACF800882BCD /* ReviewCell.m */; }; + 48EF1B681956ACF800882BCD /* ReviewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48EF1B661956ACF800882BCD /* ReviewCell.xib */; }; + 48EF1B6F195799BC00882BCD /* FilterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 48EF1B6D195799BC00882BCD /* FilterViewController.m */; }; + 48EF1B70195799BC00882BCD /* FilterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48EF1B6E195799BC00882BCD /* FilterViewController.xib */; }; 63E591F41F684901AF8C1C19 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DEC6D18C14F46F8AF2EA320 /* libPods.a */; }; /* End PBXBuildFile section */ @@ -47,16 +51,22 @@ 42FD6C4E18DC286B000BF2B9 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 42FD6C5218DC286B000BF2B9 /* Yelp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Yelp-Info.plist"; sourceTree = ""; }; 42FD6C5418DC286B000BF2B9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 42FD6C5618DC286B000BF2B9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 42FD6C5618DC286B000BF2B9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Yelp/main.m; sourceTree = SOURCE_ROOT; }; 42FD6C5818DC286B000BF2B9 /* Yelp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Yelp-Prefix.pch"; sourceTree = ""; }; 42FD6C5918DC286B000BF2B9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 42FD6C5A18DC286B000BF2B9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 42FD6C5A18DC286B000BF2B9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Yelp/AppDelegate.m; sourceTree = SOURCE_ROOT; }; 42FD6C5C18DC286B000BF2B9 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 42FD6C6218DC286B000BF2B9 /* YelpTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YelpTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42FD6C6318DC286B000BF2B9 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 42FD6C6B18DC286B000BF2B9 /* YelpTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "YelpTests-Info.plist"; sourceTree = ""; }; 42FD6C6D18DC286B000BF2B9 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 42FD6C6F18DC286B000BF2B9 /* YelpTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YelpTests.m; sourceTree = ""; }; + 48EF1B641956ACF800882BCD /* ReviewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReviewCell.h; sourceTree = ""; }; + 48EF1B651956ACF800882BCD /* ReviewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReviewCell.m; sourceTree = ""; }; + 48EF1B661956ACF800882BCD /* ReviewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ReviewCell.xib; sourceTree = ""; }; + 48EF1B6C195799BC00882BCD /* FilterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterViewController.h; sourceTree = ""; }; + 48EF1B6D195799BC00882BCD /* FilterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FilterViewController.m; sourceTree = ""; }; + 48EF1B6E195799BC00882BCD /* FilterViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FilterViewController.xib; sourceTree = ""; }; 8436EC1AAEE1439D997D29F7 /* Pods.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.xcconfig; path = Pods/Pods.xcconfig; sourceTree = ""; }; 9DEC6D18C14F46F8AF2EA320 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -101,6 +111,12 @@ 420474F818DC2B2100E88E07 /* MainViewController.h */, 420474F918DC2B2100E88E07 /* MainViewController.m */, 420474FA18DC2B2100E88E07 /* MainViewController.xib */, + 48EF1B641956ACF800882BCD /* ReviewCell.h */, + 48EF1B651956ACF800882BCD /* ReviewCell.m */, + 48EF1B661956ACF800882BCD /* ReviewCell.xib */, + 48EF1B6C195799BC00882BCD /* FilterViewController.h */, + 48EF1B6D195799BC00882BCD /* FilterViewController.m */, + 48EF1B6E195799BC00882BCD /* FilterViewController.xib */, ); name = "View Controllers"; sourceTree = ""; @@ -256,7 +272,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 48EF1B70195799BC00882BCD /* FilterViewController.xib in Resources */, 42FD6C5518DC286B000BF2B9 /* InfoPlist.strings in Resources */, + 48EF1B681956ACF800882BCD /* ReviewCell.xib in Resources */, 420474FC18DC2B2100E88E07 /* MainViewController.xib in Resources */, 42FD6C5D18DC286B000BF2B9 /* Images.xcassets in Resources */, ); @@ -310,9 +328,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 48EF1B671956ACF800882BCD /* ReviewCell.m in Sources */, 42FD6C5B18DC286B000BF2B9 /* AppDelegate.m in Sources */, 42FD6C5718DC286B000BF2B9 /* main.m in Sources */, 420474F618DC299500E88E07 /* YelpClient.m in Sources */, + 48EF1B6F195799BC00882BCD /* FilterViewController.m in Sources */, 420474FB18DC2B2100E88E07 /* MainViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Yelp/AppDelegate.m b/Yelp/AppDelegate.m index c13ec3b..ad2272a 100644 --- a/Yelp/AppDelegate.m +++ b/Yelp/AppDelegate.m @@ -15,9 +15,16 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.rootViewController = [[MainViewController alloc] init]; + //self.window.rootViewController = [[MainViewController alloc] init]; + + MainViewController *vc = [[MainViewController alloc] init]; + UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:vc]; + + self.window.rootViewController = nvc; self.window.backgroundColor = [UIColor whiteColor]; + [[UINavigationBar appearance] setBarTintColor:[UIColor redColor]]; + [self.window makeKeyAndVisible]; return YES; } diff --git a/Yelp/DetailView.h b/Yelp/DetailView.h new file mode 100644 index 0000000..8e9beb4 --- /dev/null +++ b/Yelp/DetailView.h @@ -0,0 +1,14 @@ +// +// DetailView.h +// Yelp +// +// Created by Bharti Agrawal on 6/21/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import + +@interface DetailView : UITableViewCell +@property (weak, nonatomic) IBOutlet UILabel *nameLabel; + +@end diff --git a/Yelp/DetailView.m b/Yelp/DetailView.m new file mode 100644 index 0000000..2f48bdf --- /dev/null +++ b/Yelp/DetailView.m @@ -0,0 +1,25 @@ +// +// DetailView.m +// Yelp +// +// Created by Bharti Agrawal on 6/21/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import "DetailView.h" + +@implementation DetailView + +- (void)awakeFromNib +{ + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated +{ + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/Yelp/DetailView.xib b/Yelp/DetailView.xib new file mode 100644 index 0000000..622ebb8 --- /dev/null +++ b/Yelp/DetailView.xib @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Yelp/FilterViewController.h b/Yelp/FilterViewController.h new file mode 100644 index 0000000..73b7cb1 --- /dev/null +++ b/Yelp/FilterViewController.h @@ -0,0 +1,14 @@ +// +// FilterViewController.h +// Yelp +// +// Created by Bharti Agrawal on 6/22/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import + +@interface FilterViewController : UIViewController + + +@end diff --git a/Yelp/FilterViewController.m b/Yelp/FilterViewController.m new file mode 100644 index 0000000..d2179cd --- /dev/null +++ b/Yelp/FilterViewController.m @@ -0,0 +1,220 @@ +// +// FilterViewController.m +// Yelp +// +// Created by Bharti Agrawal on 6/22/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import "FilterViewController.h" + +@interface FilterViewController () +@property (weak, nonatomic) IBOutlet UITableView *tableView; +@property (nonatomic, assign) NSInteger collapseSectionIndex; +@property (strong, nonatomic) NSArray *categoryKeys; +@property (strong, nonatomic) NSArray *sortKeys; +@property (strong, nonatomic) NSArray *radiusKeys; +@property (strong, nonatomic) NSArray *dealKeys; +@property (strong, nonatomic) NSMutableArray *collapseState; + +@end + +@implementation FilterViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + self.title = @"Filters"; + // Custom initialization + } + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + self.tableView.delegate = self; + self.tableView.dataSource = self; + + //load keys + self.categoryKeys = @[ + @{@"name": @"American (New)", @"value": @"newamerican"}, + @{@"name": @"American (Traditional)", @"value": @"tradamerican"}, + @{@"name": @"Argentine", @"value": @"argentine"}, + @{@"name": @"Asian Fusion", @"value": @"asianfusion"}, + @{@"name": @"Australian", @"value": @"australian"}, + @{@"name": @"Austrian", @"value": @"austrian"}, + @{@"name": @"Beer Garden", @"value": @"beergarden"}, + @{@"name": @"Belgian", @"value": @"belgian"}, + @{@"name": @"Brazilian", @"value": @"brazilian"}, + @{@"name": @"Breakfast & Brunch", @"value": @"breakfast_brunch"}, + @{@"name": @"Buffets", @"value": @"buffets"}, + @{@"name": @"Burgers", @"value": @"burgers"}, + @{@"name": @"Burmese", @"value": @"burmese"}, + @{@"name": @"Cafes", @"value": @"cafes"}, + @{@"name": @"Cajun/Creole", @"value": @"cajun"}, + @{@"name": @"Canadian", @"value": @"newcanadian"}, + @{@"name": @"Chinese", @"value": @"chinese"}, + @{@"name": @"Cantonese", @"value": @"cantonese"}, + @{@"name": @"Dim Sum", @"value": @"dimsum"}, + @{@"name": @"Cuban", @"value": @"cuban"}, + @{@"name": @"Diners", @"value": @"diners"}, + @{@"name": @"Dumplings", @"value": @"dumplings"}, + @{@"name": @"Ethiopian", @"value": @"ethiopian"}, + @{@"name": @"Fast Food", @"value": @"hotdogs"}, + @{@"name": @"French", @"value": @"french"}, + @{@"name": @"German", @"value": @"german"}, + @{@"name": @"Greek", @"value": @"greek"}, + @{@"name": @"Indian", @"value": @"indpak"}, + @{@"name": @"Indonesian", @"value": @"indonesian"}, + @{@"name": @"Irish", @"value": @"irish"}, + @{@"name": @"Italian", @"value": @"italian"}, + @{@"name": @"Japanese", @"value": @"japanese"}, + @{@"name": @"Jewish", @"value": @"jewish"}, + @{@"name": @"Korean", @"value": @"korean"}, + @{@"name": @"Venezuelan", @"value": @"venezuelan"}, + @{@"name": @"Malaysian", @"value": @"malaysian"}, + @{@"name": @"Pizza", @"value": @"pizza"}, + @{@"name": @"Russian", @"value": @"russian"}, + @{@"name": @"Salad", @"value": @"salad"}, + @{@"name": @"Scandinavian", @"value": @"scandinavian"}, + @{@"name": @"Seafood", @"value": @"seafood"}, + @{@"name": @"Turkish", @"value": @"turkish"}, + @{@"name": @"Vegan", @"value": @"vegan"}, + @{@"name": @"Vegetarian", @"value": @"vegetarian"}, + @{@"name": @"Vietnamese", @"value": @"vietnamese"} + ]; + + self.sortKeys = @[ + @{@"name": @"best match",@"value": @"bestmatch"}, + @{@"name": @"distance", @"value": @"distance"}, + @{@"name": @"highest rated", @"value": @"highestrated"} + ]; + + self.radiusKeys = @[ + @{@"name":@"meters", @"value":@"meters"} + ]; + + self.dealKeys = @[ + @{@"name":@"on", @"value":@"on"}, + @{@"name":@"off", @"value":@"off"} + ]; + + self.collapseState = [NSMutableArray arrayWithArray:@[@true, @false, @false, @false]]; +} + + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +#pragma mark - Table View methods + +- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{ + return 4; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + + NSInteger rows; + if ([self.collapseState[section] isEqual: @true]) + rows = 1; + else if (section == 0) + rows = self.categoryKeys.count; + else if (section ==1) + rows = self.sortKeys.count; + else if (section == 2) + rows = self.radiusKeys.count; + else if (section == 3) + rows = self.dealKeys.count; + else + rows = 0; + NSLog(@"numberOfRowsInSection Section: %d for rows: %d", section, rows); + return rows; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + + UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; + //NSLog(@"cellForRowAtIndexPath section: %d, row: %d", indexPath.section, indexPath.row); + + //NSLog(@"got cell text %@", self.categoryKeys[indexPath.row]); + //cell.textLabel.text = [NSString stringWithFormat:@"section: %d, row: %d", indexPath.section, indexPath.row]; + + if (indexPath.section == 0) { + cell.textLabel.text = self.categoryKeys[indexPath.row][@"name"]; + } else if (indexPath.section == 1) + cell.textLabel.text = self.sortKeys[indexPath.row][@"name"]; + else if (indexPath.section == 2) + cell.textLabel.text = self.radiusKeys[indexPath.row][@"name"]; + else if (indexPath.section == 3) + cell.textLabel.text = self.dealKeys[indexPath.row][@"name"]; + + return cell; +} + +-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ + + //NSLog(@"viewForHeaderInSection section %d",section); + UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 24)]; + + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 24)]; + label.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:section]; + label.backgroundColor = [UIColor clearColor]; + label.font = [UIFont boldSystemFontOfSize:14]; + + [headerView addSubview:label]; + + + + //headerView.backgroundColor = [UIColor colorWithRed:(arc4random() % 256)/255.0 green:(arc4random() % 256)/255.0 blue:(arc4random() % 256)/255.0 alpha:1]; + + return headerView; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + // The header for the section is the region name -- get this from the region at the section index. + + //NSLog(@"titleForHeaderInSection section %d",section); + if (section == 0) + return @"Categories"; + else if (section == 1) + return @"Sort By"; + else if (section == 2) + return @"Radius"; + else if (section == 3) + return @"Deals"; + return @"Section"; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ + return 24; +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + //int previousCollapseSectionIndex = self.collapseSectionIndex; + //self.collapseSectionIndex = indexPath.section; + if ([self.collapseState[indexPath.section] isEqual: @true]) + self.collapseState[indexPath.section] = @false; + else + self.collapseState[indexPath.section] = @true; + + //NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSetWithIndex:previousCollapseSectionIndex]; + //[indexSet addIndex:self.collapseSectionIndex]; + + //[tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; + + [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark; + [tableView reloadData]; +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone; +} + +@end diff --git a/Yelp/FilterViewController.xib b/Yelp/FilterViewController.xib new file mode 100644 index 0000000..dfbdab5 --- /dev/null +++ b/Yelp/FilterViewController.xib @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Yelp/Images.xcassets/filterButton.imageset/Contents.json b/Yelp/Images.xcassets/filterButton.imageset/Contents.json new file mode 100644 index 0000000..8a4ea0b --- /dev/null +++ b/Yelp/Images.xcassets/filterButton.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Yelp/MainViewController.h b/Yelp/MainViewController.h index b072ae7..e3aa581 100644 --- a/Yelp/MainViewController.h +++ b/Yelp/MainViewController.h @@ -8,6 +8,6 @@ #import -@interface MainViewController : UIViewController +@interface MainViewController : UIViewController @end diff --git a/Yelp/MainViewController.m b/Yelp/MainViewController.m index 86c77a0..05677e3 100644 --- a/Yelp/MainViewController.m +++ b/Yelp/MainViewController.m @@ -8,16 +8,23 @@ #import "MainViewController.h" #import "YelpClient.h" +#import "ReviewCell.h" +#import "FilterViewController.h" +#import "UIImageView+AFNetworking.h" -NSString * const kYelpConsumerKey = @"vxKwwcR_NMQ7WaEiQBK_CA"; -NSString * const kYelpConsumerSecret = @"33QCvh5bIF5jIHR5klQr7RtBDhQ"; -NSString * const kYelpToken = @"uRcRswHFYa1VkDrGV6LAW2F8clGh5JHV"; -NSString * const kYelpTokenSecret = @"mqtKIxMIR4iBtBPZCmCLEb-Dz3Y"; +NSString * const kYelpConsumerKey = @"SxgSKMU2aA4RTt8wv6b8JQ"; +NSString * const kYelpConsumerSecret = @"kMCWuKvORR0J4B-_Fpqf0dnxRmY"; +NSString * const kYelpToken = @"7RYy976gUZ2QjZxJ7S9PtFlGzOeyNAyw"; +NSString * const kYelpTokenSecret = @"LQs24GHFrXeVlqoGG2Ba1vhOPdE"; @interface MainViewController () - +@property (weak, nonatomic) IBOutlet UITableView *tableView; +@property (nonatomic, strong) NSArray *reviews; @property (nonatomic, strong) YelpClient *client; +- (void)loadReviews:(NSString *)searchTerm; +- (void)onFilterButton; + @end @implementation MainViewController @@ -26,21 +33,48 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { - // You can register for Yelp API keys here: http://www.yelp.com/developers/manage_api_keys - self.client = [[YelpClient alloc] initWithConsumerKey:kYelpConsumerKey consumerSecret:kYelpConsumerSecret accessToken:kYelpToken accessSecret:kYelpTokenSecret]; - - [self.client searchWithTerm:@"Thai" success:^(AFHTTPRequestOperation *operation, id response) { - NSLog(@"response: %@", response); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - NSLog(@"error: %@", [error description]); - }]; + [self loadReviews:@"Thai"]; } return self; } +-(void)loadReviews:(NSString *)searchTerm +{ + // You can register for Yelp API keys here: http://www.yelp.com/developers/manage_api_keys + self.client = [[YelpClient alloc] initWithConsumerKey:kYelpConsumerKey consumerSecret:kYelpConsumerSecret accessToken:kYelpToken accessSecret:kYelpTokenSecret]; + + [self.client searchWithTerm:searchTerm success:^(AFHTTPRequestOperation *operation, id response) { + //NSLog(@"response: %@", response); + self.reviews = response[@"businesses"]; + [self.tableView reloadData]; + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + NSLog(@"error: %@", [error description]); + }]; +} + - (void)viewDidLoad { [super viewDidLoad]; + self.tableView.delegate = self; + self.tableView.dataSource = self; + + [self.tableView registerNib:[UINib nibWithNibName:@"ReviewCell" bundle:nil] forCellReuseIdentifier:@"ReviewCell"]; + + self.tableView.rowHeight = 90; + + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Filter" style:UIBarButtonItemStylePlain target:self action:@selector(onFilterButton)]; + + // Configure the left button in nav bar + /*UIImage *leftButtonImage = [[UIImage imageNamed:@"filterButton"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithImage:leftButtonImage style:UIBarButtonItemStylePlain target:self action:@selector(onFilterButton:)]; + self.navigationItem.leftBarButtonItem = leftButton;*/ + + //search bar in navbar + UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 200, 30)]; + searchBar.delegate = self; + self.navigationItem.titleView = searchBar; + + //[self.tableView reloadData]; // Do any additional setup after loading the view from its nib. } @@ -50,4 +84,62 @@ - (void)didReceiveMemoryWarning // Dispose of any resources that can be recreated. } +#pragma mark - Table View methods +- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ + return self.reviews.count; + //return 10; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ + NSLog(@"cellForRowAtIndexPath: %d", indexPath.row); + + /*UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; + + NSDictionary *review = self.reviews[indexPath.row]; + cell.textLabel.text= review[@"name"]; + return cell;*/ + + ReviewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ReviewCell"]; + NSDictionary *review = self.reviews[indexPath.row]; + + cell.nameLabel.text = review[@"name"]; + cell.distanceLabel.text = review[@"distance"]; + + NSString *numReviews = [NSString stringWithFormat:@"%@", review[@"review_count"]]; + numReviews = [numReviews stringByAppendingFormat:@"Reviews"]; + cell.numReviewsLabel.text = numReviews; + + cell.addressLabel.text = review[@"location"][@"address"][0]; + //cell.tagsLabel.text = review[@"synopsis"]; + //cell.dollarsLabel.text = review[@"synopsis"]; + + NSString *imageUrl = review[@"image_url"]; + NSURL *url = [NSURL URLWithString:imageUrl]; + + //[cell.posterView setImageWithURL:url]; + //UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]]; + + [cell.posterView setImageWithURL:url]; + + NSString *ratingUrl = review[@"rating_img_url"]; + NSURL *rurl = [NSURL URLWithString:ratingUrl]; + + //[cell.posterView setImageWithURL:url]; + //UIImage *rimage = [UIImage imageWithData: [NSData dataWithContentsOfURL:rurl]]; + + [cell.ratingStarView setImageWithURL:rurl]; + + return cell; +} + +- (void)onFilterButton { + [self.navigationController pushViewController:[[FilterViewController alloc] init] animated:YES]; +} + +- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText { + NSLog(@"in textDidChagne @%@", searchText); +} + + + @end diff --git a/Yelp/MainViewController.xib b/Yelp/MainViewController.xib index 75b6e65..84eae97 100644 --- a/Yelp/MainViewController.xib +++ b/Yelp/MainViewController.xib @@ -1,11 +1,12 @@ - + + @@ -14,17 +15,22 @@ - + + + + + + diff --git a/Yelp/ReviewCell.h b/Yelp/ReviewCell.h new file mode 100644 index 0000000..9da29fc --- /dev/null +++ b/Yelp/ReviewCell.h @@ -0,0 +1,21 @@ +// +// ReviewCell.h +// Yelp +// +// Created by Bharti Agrawal on 6/21/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import + +@interface ReviewCell : UITableViewCell +@property (weak, nonatomic) IBOutlet UILabel *nameLabel; +@property (weak, nonatomic) IBOutlet UILabel *distanceLabel; +@property (weak, nonatomic) IBOutlet UILabel *numReviewsLabel; +@property (weak, nonatomic) IBOutlet UILabel *addressLabel; + +@property (weak, nonatomic) IBOutlet UILabel *tagsLabel; +@property (weak, nonatomic) IBOutlet UIImageView *posterView; +@property (weak, nonatomic) IBOutlet UILabel *dollarsLabel; +@property (weak, nonatomic) IBOutlet UIImageView *ratingStarView; +@end diff --git a/Yelp/ReviewCell.m b/Yelp/ReviewCell.m new file mode 100644 index 0000000..1c43113 --- /dev/null +++ b/Yelp/ReviewCell.m @@ -0,0 +1,25 @@ +// +// ReviewCell.m +// Yelp +// +// Created by Bharti Agrawal on 6/21/14. +// Copyright (c) 2014 codepath. All rights reserved. +// + +#import "ReviewCell.h" + +@implementation ReviewCell + +- (void)awakeFromNib +{ + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated +{ + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/Yelp/ReviewCell.xib b/Yelp/ReviewCell.xib new file mode 100644 index 0000000..4a5891f --- /dev/null +++ b/Yelp/ReviewCell.xib @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/yelp.gif b/yelp.gif new file mode 100644 index 0000000..91e79fa Binary files /dev/null and b/yelp.gif differ