Commit f4173d1653d2ff87b427eda6d01d5eca88236265

Authored by nvtu11790@gmail.com
1 parent c4525f8715

Add API for request history list and graph in today with selected type and mode

Showing 9 changed files with 253 additions and 39 deletions Side-by-side Diff

LifeLog/LifeLog.xcodeproj/project.pbxproj
... ... @@ -46,6 +46,7 @@
46 46 9CBDA1001F2F03810055DED1 /* RegisterViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9CBDA0FE1F2F03810055DED1 /* RegisterViewController.xib */; };
47 47 E9373E471F3596940059355A /* AutoTransLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = E9373E461F3596940059355A /* AutoTransLabel.m */; };
48 48 E9373E4A1F35AA180059355A /* HistoryObject.m in Sources */ = {isa = PBXBuildFile; fileRef = E9373E491F35AA180059355A /* HistoryObject.m */; };
  49 + E9373E4D1F361A230059355A /* HistoryGraphObject.m in Sources */ = {isa = PBXBuildFile; fileRef = E9373E4C1F361A230059355A /* HistoryGraphObject.m */; };
49 50 E99E13AB1F336F3600C78787 /* CollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = E99E13AA1F336F3600C78787 /* CollectionView.m */; };
50 51 E99E13AD1F336F4500C78787 /* CollectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E99E13AC1F336F4500C78787 /* CollectionView.xib */; };
51 52 E99E13B11F33720600C78787 /* LabelCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E99E13AF1F33720600C78787 /* LabelCollectionViewCell.m */; };
... ... @@ -143,6 +144,8 @@
143 144 E9373E461F3596940059355A /* AutoTransLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoTransLabel.m; sourceTree = "<group>"; };
144 145 E9373E481F35AA180059355A /* HistoryObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryObject.h; sourceTree = "<group>"; };
145 146 E9373E491F35AA180059355A /* HistoryObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryObject.m; sourceTree = "<group>"; };
  147 + E9373E4B1F361A230059355A /* HistoryGraphObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HistoryGraphObject.h; sourceTree = "<group>"; };
  148 + E9373E4C1F361A230059355A /* HistoryGraphObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HistoryGraphObject.m; sourceTree = "<group>"; };
146 149 E99E13A91F336F3600C78787 /* CollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionView.h; sourceTree = "<group>"; };
147 150 E99E13AA1F336F3600C78787 /* CollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionView.m; sourceTree = "<group>"; };
148 151 E99E13AC1F336F4500C78787 /* CollectionView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CollectionView.xib; sourceTree = "<group>"; };
... ... @@ -216,6 +219,8 @@
216 219 6E18CEDD1F2E46570029891F /* Entities.h */,
217 220 E9373E481F35AA180059355A /* HistoryObject.h */,
218 221 E9373E491F35AA180059355A /* HistoryObject.m */,
  222 + E9373E4B1F361A230059355A /* HistoryGraphObject.h */,
  223 + E9373E4C1F361A230059355A /* HistoryGraphObject.m */,
219 224 );
220 225 name = Model;
221 226 sourceTree = "<group>";
... ... @@ -713,6 +718,7 @@
713 718 6E18CED31F2E39DB0029891F /* LoginViewController.m in Sources */,
714 719 6E84E3761F27A701001EB88E /* main.m in Sources */,
715 720 6E84E3B51F27A98B001EB88E /* HistoryViewController.m in Sources */,
  721 + E9373E4D1F361A230059355A /* HistoryGraphObject.m in Sources */,
716 722 6E84E3BF1F27A9B1001EB88E /* SNSViewController.m in Sources */,
717 723 );
718 724 runOnlyForDeploymentPostprocessing = 0;
LifeLog/LifeLog/Entities.h
... ... @@ -9,6 +9,9 @@
9 9 #ifndef Entities_h
10 10 #define Entities_h
11 11  
  12 +#import <MBProgressHUD/MBProgressHUD.h>
  13 +
  14 +#import "HistoryGraphObject.h"
12 15 #import "HistoryObject.h"
13 16 #import "User.h"
14 17  
LifeLog/LifeLog/HistoryGraphObject.h
  1 +//
  2 +// HistoryGraphObject.h
  3 +// LifeLog
  4 +//
  5 +// Created by nvtu on 8/5/17.
  6 +// Copyright © 2017 PhongNV. All rights reserved.
  7 +//
  8 +
  9 +#import <Foundation/Foundation.h>
  10 +
  11 +@interface HistoryGraphObject : NSObject
  12 +
  13 +@property (nonatomic, strong) NSMutableArray * arrayTime;
  14 +@property (nonatomic, strong) NSMutableArray * arrayStep;
  15 +
  16 +-(id) initWithData : (NSDictionary *) dict;
  17 +
  18 +@end
LifeLog/LifeLog/HistoryGraphObject.m
  1 +//
  2 +// HistoryGraphObject.m
  3 +// LifeLog
  4 +//
  5 +// Created by nvtu on 8/5/17.
  6 +// Copyright © 2017 PhongNV. All rights reserved.
  7 +//
  8 +
  9 +#import "HistoryGraphObject.h"
  10 +
  11 +@implementation HistoryGraphObject
  12 +
  13 +-(id) initWithData : (NSDictionary *) dict {
  14 +
  15 + if([dict objectForKey:@"data"] != nil) {
  16 + self.arrayStep = [[NSMutableArray alloc] init];
  17 + self.arrayTime = [[NSMutableArray alloc] init];
  18 + NSArray *arrayGraph = dict[@"data"];
  19 + for(NSDictionary *sub in arrayGraph) {
  20 + if([sub objectForKey:@"hour"] != nil && [sub objectForKey:@"step"] != nil) {
  21 + [self.arrayTime addObject:[sub objectForKey:@"hour"]];
  22 + [self.arrayStep addObject:[sub objectForKey:@"step"]];
  23 + }
  24 + }
  25 + }
  26 + else {
  27 + return nil;
  28 + }
  29 + return self;
  30 +}
  31 +
  32 +
  33 +@end
LifeLog/LifeLog/HistoryObject.m
... ... @@ -24,16 +24,27 @@
24 24 self.percent = [dict[@"percent"] floatValue];
25 25 }
26 26 if([dict objectForKey:@"distance"] != nil) {
27   - self.distance = [dict[@"distance"] floatValue];
  27 + if([dict[@"distance"] isKindOfClass:[NSString class]]) {
  28 + NSString *distance = dict[@"distance"];
  29 + self.distance = [distance floatValue];
  30 + }
  31 + else {
  32 + self.distance = [dict[@"distance"] floatValue];
  33 + }
28 34 }
29 35 if([dict objectForKey:@"kcal"] != nil) {
30 36 self.calories = [dict[@"kcal"] floatValue];
31 37 }
32 38 if([dict objectForKey:@"time"] != nil) {
33   - self.time = dict[@"time"];
  39 + if([dict[@"time"] isKindOfClass:[NSString class]]) {
  40 + self.time = dict[@"time"];
  41 + }
  42 + else {
  43 + self.time = @"0:0";
  44 + }
34 45 }
35 46 if([dict objectForKey:@"date"] != nil) {
36   - NSString *dateString = dict[@"time"];
  47 + NSString *dateString = dict[@"date"];
37 48 NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
38 49 [dateFormat setDateFormat:@"yyyy-MM-dd"];
39 50 self.date = [dateFormat dateFromString:dateString];
LifeLog/LifeLog/HistoryViewController.h
... ... @@ -14,8 +14,12 @@
14 14 #import "Entities.h"
15 15  
16 16 @interface HistoryViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UIScrollViewDelegate> {
17   - NSDate * _currentDate;
18   - HistoryObject * _currentHistoryObject;
  17 + NSDate * _curDate;
  18 + HistoryObject * _curHisObj;
  19 + HistoryGraphObject * _curHisGraphObj;
  20 + NSMutableArray * _curHisList;
  21 +
  22 + int _curPageIndex;
19 23 }
20 24  
21 25 @property (weak, nonatomic) IBOutlet UILabel *lblHeader;
LifeLog/LifeLog/HistoryViewController.m
... ... @@ -27,7 +27,8 @@
27 27 [self setupView];
28 28 [self setupChartView];
29 29  
30   - _currentDate = [NSDate date];
  30 + _curDate = [NSDate date];
  31 + _curHisList = [[NSMutableArray alloc] init];
31 32  
32 33 [self callRequestToUpdateData];
33 34  
... ... @@ -75,15 +76,6 @@
75 76 [self.viewCollectionShare setArrayTitle:shareTitle];
76 77 }
77 78  
78   --(void) updateView {
79   - self.lblStep.text = [NSString stringWithFormat:@"%d", _currentHistoryObject.step];
80   - self.lblRemaining.text = [NSString stringWithFormat:@"%d", _currentHistoryObject.missing];
81   - self.lblPercent.text = [NSString stringWithFormat:@"%0.2f", _currentHistoryObject.percent * 100];
82   - self.lblCalories.text = [NSString stringWithFormat:@"%1.0f", _currentHistoryObject.calories];
83   - self.lblDistance.text = [NSString stringWithFormat:@"%0.1f", _currentHistoryObject.distance];
84   - self.lblTime.text = _currentHistoryObject.time;
85   -}
86   -
87 79 - (void)setupChartView {
88 80 self.viewBarChart.chartDescription.enabled = NO;
89 81 self.viewBarChart.leftAxis.drawGridLinesEnabled = NO;
90 82  
91 83  
... ... @@ -103,14 +95,22 @@
103 95  
104 96 self.viewBarChart.leftAxis.drawAxisLineEnabled = NO;
105 97 self.viewBarChart.rightAxis.drawAxisLineEnabled = NO;
106   -
107   - /*fake data for test*/
  98 +}
  99 +
  100 +-(void) updateView {
  101 + self.lblStep.text = [NSString stringWithFormat:@"%d", _curHisObj.step];
  102 + self.lblRemaining.text = [NSString stringWithFormat:@"%d", _curHisObj.missing];
  103 + self.lblPercent.text = [NSString stringWithFormat:@"%0.2f", _curHisObj.percent * 100];
  104 + self.lblCalories.text = [NSString stringWithFormat:@"%0.2f", _curHisObj.calories];
  105 + self.lblDistance.text = [NSString stringWithFormat:@"%0.1f", _curHisObj.distance];
  106 + self.lblTime.text = _curHisObj.time;
  107 +}
  108 +
  109 +-(void) updateGraphView {
108 110 NSMutableArray *yVals = [[NSMutableArray alloc] init];
109   -
110   - for (int i = 0; i < 24; i++)
  111 + for (int i = 0; i < _curHisGraphObj.arrayStep.count; i++)
111 112 {
112   - double val = (double) (arc4random_uniform(100));
113   - [yVals addObject:[[BarChartDataEntry alloc] initWithX:i y:val]];
  113 + [yVals addObject:[[BarChartDataEntry alloc] initWithX:i y:[[_curHisGraphObj.arrayStep objectAtIndex:i] doubleValue]]];
114 114 }
115 115  
116 116 BarChartDataSet *set1 = nil;
117 117  
... ... @@ -131,27 +131,71 @@
131 131  
132 132 BarChartData *data = [[BarChartData alloc] initWithDataSets:dataSets];
133 133 data.barWidth = 0.5f;
134   -
  134 +
135 135 self.viewBarChart.data = data;
136 136 }
137 137 }
138 138  
139 139 -(void) callRequestToUpdateData {
140   - [[ServerAPI server] requestHistory:[[NSUserDefaults standardUserDefaults] stringForKey:kToken] atDate:_currentDate withType:self.viewCollectionType.getCurrentIndex andMode:self.viewCollectionMode.getCurrentIndex + 1 CompletionHandler:^(HistoryObject *object, NSError *error) {
141   - HistoryViewController __weak *weakSelf = self;
142   - if(error == nil) {
143   - _currentHistoryObject = object;
144   - dispatch_async(dispatch_get_main_queue(), ^{
145   - [self updateView];
146   - });
147   - }
148   - else {
149   - dispatch_async(dispatch_get_main_queue(), ^{
150   - NSString *message = [error.userInfo objectForKey:@"message"];
151   - [Utilities showErrorMessage:message withViewController:weakSelf];
152   - });
153   - }
154   - }];
  140 + MBProgressHUD *hudView = [MBProgressHUD showHUDAddedTo:self.view animated:true];
  141 + NSString * token = [[NSUserDefaults standardUserDefaults] stringForKey:kToken];
  142 + int type = self.viewCollectionType.getCurrentIndex;
  143 + int mode = self.viewCollectionMode.getCurrentIndex + 1;
  144 +
  145 + if(self.tableListHistory.alpha == 0.0) {
  146 + [[ServerAPI server] requestHistory:token atDate:_curDate withType:type andMode:mode CompletionHandler:^(HistoryObject *object, NSError *error) {
  147 + HistoryViewController __weak *weakSelf = self;
  148 + if(error == nil) {
  149 + _curHisObj = object;
  150 + dispatch_async(dispatch_get_main_queue(), ^{
  151 + [hudView hideAnimated:true];
  152 + [weakSelf updateView];
  153 + });
  154 + }
  155 + else {
  156 + dispatch_async(dispatch_get_main_queue(), ^{
  157 + [hudView hideAnimated:true];
  158 + NSString *message = [error.userInfo objectForKey:@"message"];
  159 + [Utilities showErrorMessage:message withViewController:weakSelf];
  160 + });
  161 + }
  162 + }];
  163 +
  164 + [[ServerAPI server] requestHistoryGraph:token withType:type andMode:mode CompletionHandler:^(HistoryGraphObject *object, NSError *error) {
  165 + HistoryViewController __weak *weakSelf = self;
  166 + if(error == nil) {
  167 + _curHisGraphObj = object;
  168 + dispatch_async(dispatch_get_main_queue(), ^{
  169 + [self updateGraphView];
  170 + });
  171 + }
  172 + else {
  173 + dispatch_async(dispatch_get_main_queue(), ^{
  174 + NSString *message = [error.userInfo objectForKey:@"message"];
  175 + [Utilities showErrorMessage:message withViewController:weakSelf];
  176 + });
  177 + }
  178 + }];
  179 + }
  180 + else {
  181 + [[ServerAPI server] requestHistoryList:token withType:type andMode:mode AtPage:1 CompletionHandler:^(NSMutableArray *object, NSError *error) {
  182 + HistoryViewController __weak *weakSelf = self;
  183 + if(error == nil) {
  184 + _curHisList = object;
  185 + dispatch_async(dispatch_get_main_queue(), ^{
  186 + [hudView hideAnimated:true];
  187 + [weakSelf.tableListHistory reloadData];
  188 + });
  189 + }
  190 + else {
  191 + dispatch_async(dispatch_get_main_queue(), ^{
  192 + [hudView hideAnimated:true];
  193 + NSString *message = [error.userInfo objectForKey:@"message"];
  194 + [Utilities showErrorMessage:message withViewController:weakSelf];
  195 + });
  196 + }
  197 + }];
  198 + }
155 199 }
156 200  
157 201 #pragma mark IBAction
158 202  
159 203  
160 204  
... ... @@ -161,16 +205,37 @@
161 205 self.tableListHistory.alpha = alphaValue;
162 206 self.scrollView.alpha = 1.0 - alphaValue;
163 207 } completion:^(bool completed) {
  208 + [self callRequestToUpdateData];
164 209 }];
165 210 }
166 211  
167 212 #pragma mark UITableView Delegate
  213 +- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
  214 + if(_curHisList == nil || _curHisList.count == 0) {
  215 + UILabel * noDataLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
  216 + noDataLabel.text = @"No data available";
  217 + noDataLabel.backgroundColor = [UIColor clearColor];
  218 + noDataLabel.textColor = [UIColor whiteColor];
  219 + noDataLabel.textAlignment = NSTextAlignmentCenter;
  220 + tableView.backgroundView = noDataLabel;
  221 + tableView.backgroundView.layer.zPosition -= 1;
  222 + return 0;
  223 + }
  224 + tableView.backgroundView = nil;
  225 + return 1;
  226 +}
  227 +
168 228 - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
169   - return 4;
  229 + return _curHisList.count;
170 230 }
171 231  
172 232 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
173 233 HistoryListTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"HistoryListCell"];
  234 + HistoryObject * obj = [_curHisList objectAtIndex:indexPath.row];
  235 + cell.lblStep.text = [NSString stringWithFormat:@"%d", obj.step];
  236 + cell.lblPower.text = [NSString stringWithFormat:@"%0.2f", obj.calories];
  237 + cell.lblDistance.text = [NSString stringWithFormat:@"%0.1f", obj.distance];
  238 + cell.lblDuration.text = obj.time;
174 239 return cell;
175 240 }
176 241  
LifeLog/LifeLog/ServerAPI.h
... ... @@ -23,6 +23,7 @@
23 23 - (void)confirmForgetPass:(NSString *)email withConfirm:(NSString *)confirm CompletionHandler:(void (^)(NSError *)) completion;
24 24  
25 25 - (void) requestHistory:(NSString *)token atDate:(NSDate *)date withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryObject *, NSError *)) completion;
26   -
  26 +- (void) requestHistoryGraph:(NSString *)token withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryGraphObject *, NSError *)) completion;
  27 +- (void) requestHistoryList:(NSString *)token withType:(int)type andMode:(int) mode AtPage:(int) page CompletionHandler:(void (^)(NSMutableArray *, NSError *)) completion;
27 28 @end
LifeLog/LifeLog/ServerAPI.m
... ... @@ -304,6 +304,79 @@
304 304 }];
305 305 }
306 306  
  307 +- (void) requestHistoryGraph:(NSString *)token withType:(int)type andMode:(int) mode CompletionHandler:(void (^)(HistoryGraphObject *, NSError *)) completion {
  308 + NSString *url = [kServerAddress stringByAppendingFormat:@"/api/history/graph/%@/%d", [self convertIntToString:type], mode];
  309 + NSLog(@"requestHistoryGraph link %@", url);
  310 + [self _request:url method:@"GET" token:token paras:nil completion:^(NSData *data, NSError *error) {
  311 +
  312 + if (completion == NULL) {
  313 + return ;
  314 + }
  315 +
  316 + if (error == nil)
  317 + {
  318 + NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error];
  319 + NSLog(@"%@", dataResult);
  320 + int status = [dataResult[@"status"] intValue];
  321 + if (status == 1) { // status = 1 success
  322 + HistoryGraphObject * object = [[HistoryGraphObject alloc] initWithData:dataResult[@"result"]];
  323 + completion(object, nil);
  324 + }
  325 + else {
  326 + NSString *message = dataResult[@"message"];
  327 + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
  328 + completion(nil, errorObject);
  329 + }
  330 + }
  331 + else
  332 + {
  333 + completion(nil, error);
  334 + }
  335 + }];
  336 +}
  337 +
  338 +- (void) requestHistoryList:(NSString *)token withType:(int)type andMode:(int) mode AtPage:(int) page CompletionHandler:(void (^)(NSMutableArray *, NSError *)) completion {
  339 + NSString *url = [kServerAddress stringByAppendingFormat:@"/api/history/list/%@/%d?page=%d&record=50", [self convertIntToString:type], mode, page];
  340 + NSLog(@"requestHistoryList link %@", url);
  341 + [self _request:url method:@"GET" token:token paras:nil completion:^(NSData *data, NSError *error) {
  342 +
  343 + if (completion == NULL) {
  344 + return ;
  345 + }
  346 +
  347 + if (error == nil)
  348 + {
  349 + NSDictionary *dataResult = [NSJSONSerialization JSONObjectWithData:data options: NSJSONReadingAllowFragments error: &error];
  350 + NSLog(@"%@", dataResult);
  351 + int status = [dataResult[@"status"] intValue];
  352 + if (status == 1) { // status = 1 success
  353 + if(dataResult[@"result"] != nil) {
  354 + NSArray * array = dataResult[@"result"][@"data"];
  355 + NSMutableArray * arrayHistory = [[NSMutableArray alloc] init];
  356 + for(NSDictionary * dict in array) {
  357 + HistoryObject * object = [[HistoryObject alloc] initWithData:dict];
  358 + [arrayHistory addObject:object];
  359 + }
  360 + completion(arrayHistory, nil);
  361 + }
  362 + else {
  363 + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":@"Unknown Error"}];
  364 + completion(nil, errorObject);
  365 + }
  366 + }
  367 + else {
  368 + NSString *message = dataResult[@"message"];
  369 + NSError *errorObject = [NSError errorWithDomain:@"LifeLog_Domain" code:-1 userInfo:@{@"message":message}];
  370 + completion(nil, errorObject);
  371 + }
  372 + }
  373 + else
  374 + {
  375 + completion(nil, error);
  376 + }
  377 + }];
  378 +}
  379 +
307 380 #pragma mark - Private Function
308 381 - (NSData *) _encodeDictionary: (NSDictionary *) dictionary
309 382 {