Commit 6da6b554 authored by Wei Han's avatar Wei Han

code update

parent 9e06acac
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
......
......@@ -512,7 +512,7 @@
return;
}
[APIClient fetchCancelAppointment:self.appointmentData[@"appointment_id"]
[APIClient requestCancelAppointment:self.appointmentData[@"appointment_id"]
reason:remarks
completion:^(NSDictionary *data, NSError *error)
{
......
......@@ -285,7 +285,7 @@
- (void)viewDidLoad {
[super viewDidLoad];
[self fetchAccessItem];
[self requestAccessItem];
self.view.backgroundColor = UIColor.whiteColor;
[self setupHeader];
......@@ -361,7 +361,7 @@
__weak typeof(self) weakSelf = self;
[self.tableView addPullToRefresh:^(UIRefreshControl *refresh) {
[weakSelf fetchAccessItem];
[weakSelf requestAccessItem];
}];
[self.view addSubview:self.tableView];
......@@ -375,8 +375,8 @@
}
#pragma mark - Api
- (void)fetchAccessItem{
[APIClient fetchAccessItem:@"135"
- (void)requestAccessItem{
[APIClient requestAccessItem:@"135"
completion:^(BOOL success, NSDictionary *data, NSError *error) {
NSLog(@"📦 Received General Info Data: %@", data);
......
......@@ -43,7 +43,7 @@
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
[self fetchGeneralInfo];
[self requestGeneralInfo];
[self setupNavBar];
[self setupUnitInfoHeader];
[self setupTabsBar];
......@@ -931,7 +931,7 @@
return;
}
[APIClient fetchCancelAppointment:self.appointmentData[@"id"]
[APIClient requestCancelAppointment:self.appointmentData[@"id"]
reason:remarks
completion:^(NSDictionary *data, NSError *error)
{
......@@ -965,8 +965,8 @@
}];
}
-(void) fetchGeneralInfo {
[APIClient fetchGeneralInfo:^(NSDictionary *data, NSError *error) {
-(void) requestGeneralInfo {
[APIClient requestGeneralInfo:^(NSDictionary *data, NSError *error) {
if (error) return;
NSDictionary *generalInfo = data[@"Data"];
self.floorPlanImage = generalInfo[@"image"];
......
......@@ -138,7 +138,7 @@
[self setupListingView];
[self setupFilterOverlay];
[self setupLoadingOverlay];
[self fetchDashboardInfo];
[self requestDashboardInfo];
}
#pragma mark - Top Bar
......@@ -679,7 +679,7 @@
}
- (void)onRefresh {
[self fetchDashboardInfo];
[self requestDashboardInfo];
}
#pragma mark - Bottom Button
......@@ -924,10 +924,10 @@
}
#pragma mark - api
- (void)fetchDashboardInfo {
- (void)requestDashboardInfo {
[self.loadingView startAnimating];
[APIClient fetchDashboardInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestDashboardInfo:^(NSDictionary *data, NSError *error) {
[self.loadingView stopAnimating];
......
......@@ -12,6 +12,7 @@
#import "GeneralInfoViewController.h"
#import "AccessItemViewController.h"
#import "OfflineSyncManager.h"
#import "LocalStorage.h"
@interface DashboardViewController ()
......@@ -81,7 +82,6 @@
NSLog(@"dashboard.drawerController = %@", self.drawerController);
// [[OfflineSyncManager shared] clearOfflineQueue];
}
- (void)viewWillAppear:(BOOL)animated {
......@@ -113,13 +113,13 @@
__block NSDictionary *announcementData = nil;
dispatch_group_enter(group);
[APIClient fetchDashboardInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestDashboardInfo:^(NSDictionary *data, NSError *error) {
if (!error) dashboardData = data;
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[APIClient fetchAnnouncement:^(NSDictionary *data, NSError *error) {
[APIClient requestAnnouncement:^(NSDictionary *data, NSError *error) {
if (!error) announcementData = data;
dispatch_group_leave(group);
}];
......@@ -593,7 +593,7 @@
NSDictionary *appData = data[@"AppData"];
if (![appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"Announcement fetch failed: %@", appData[@"message"]);
NSLog(@"Announcement request failed: %@", appData[@"message"]);
return;
}
......
......@@ -83,7 +83,7 @@ typedef struct {
self.documentsContainer.clipsToBounds = YES;
self.formsContainer.clipsToBounds = YES;
[self fetchGeneralInfo];
[self requestGeneralInfo];
[self setupTopBar];
[self setupTabControl];
[self setupScrollView];
......@@ -540,8 +540,8 @@ typedef struct {
}
#pragma mark - api
- (void)fetchGeneralInfo {
[APIClient fetchGeneralInfo:^(NSDictionary *data, NSError *error) {
- (void)requestGeneralInfo {
[APIClient requestGeneralInfo:^(NSDictionary *data, NSError *error) {
if (error || !data) {
NSLog(@"❌ General info error: %@", error.localizedDescription);
return;
......
......@@ -67,11 +67,11 @@
}
- (void)handleGetUnitPlan {
NSLog(@"🌐 Fetching Unit Plan data...");
NSLog(@"🌐 requesting Unit Plan data...");
[APIClient fetchGetUnitPlan:^(NSDictionary *data, NSError *error) {
[APIClient requestGetUnitPlan:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ Unit Plan fetch failed: %@", error.localizedDescription);
NSLog(@"❌ Unit Plan request failed: %@", error.localizedDescription);
return;
}
......@@ -165,7 +165,6 @@
}];
}
- (void)highlightExistingIssueAtCoordinates:(CGFloat)x Y:(CGFloat)y {
NSLog(@"📍 Highlighting existing issue at (%.2f, %.2f)", x, y);
......@@ -702,20 +701,19 @@
}
if (self.locationID) {
NSLog(@"📡 Fetching settings for location %@ and plan %@", self.locationID, self.planID);
NSLog(@"📡 requesting settings for location %@ and plan %@", self.locationID, self.planID);
[self handleSettingsByLocation:self.locationID planID:self.planID];
} else {
NSLog(@"⚠️ No match found for %@", self.selectedLocation);
}
}
- (void)handleSettingsByLocation:(NSString *)locationID planID:(NSString *)planID {
[APIClient fetchSettingsByLocation:locationID
[APIClient requestSettingsByLocation:locationID
projectID:@"8"
completion:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ Error fetching settings: %@", error);
NSLog(@"❌ Error requesting settings: %@", error);
return;
}
......
......@@ -126,10 +126,10 @@
#pragma mark - API request/response
- (void)handleIssues {
[APIClient fetchHistory:self.issueID
[APIClient requestHistory:self.issueID
completion:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ Error fetching history: %@", error);
NSLog(@"❌ Error requesting history: %@", error);
return;
}
......
......@@ -298,11 +298,11 @@
#pragma mark - Networking
- (void)handleGetIssue {
NSLog(@"🌐 Fetching Issue data...");
NSLog(@"🌐 requesting Issue data...");
[APIClient fetchIssues:^(NSDictionary *data, NSError *error) {
[APIClient requestIssues:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ Issue fetch failed: %@", error.localizedDescription);
NSLog(@"❌ Issue request failed: %@", error.localizedDescription);
return;
}
......
......@@ -174,7 +174,7 @@
[self setupSearchBar];
[self setupTableView];
[self setupBottomBar];
[self fetchIssues];
[self requestIssues];
}
- (void)viewWillAppear:(BOOL)animated {
......@@ -382,8 +382,8 @@
}
#pragma mark - Data
- (void)fetchIssues {
[APIClient fetchIssues:^(NSDictionary *data, NSError *error) {
- (void)requestIssues {
[APIClient requestIssues:^(NSDictionary *data, NSError *error) {
if (error) return;
NSArray *allIssues = data[@"Data"] ?: @[];
......
......@@ -264,7 +264,7 @@
- (void)requestDeleteIssue:(NSString *)issueID remarks:(NSString *)remarks {
NSLog(@"🚀 Sending DELETE ISSUE for ID=%@, remarks=%@", issueID, remarks);
[APIClient fetchDeleteIssue:issueID remarks:remarks completion:^(NSDictionary *data, NSError *error) {
[APIClient requestDeleteIssue:issueID remarks:remarks completion:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"Error %@", error.localizedDescription);
return;
......@@ -301,7 +301,7 @@
-(void)requestVoidIssue:(NSArray *)ids remarks:(NSString *)remarks {
NSLog(@"🚀 Sending VOID ISSUE for ID=%@, remarks=%@", self.selectedIssues, remarks);
[APIClient fetchVoidIssue:ids
[APIClient requestVoidIssue:ids
remarks:remarks
completion:^(NSDictionary *data, NSError *error) {
if (error) {
......
//// SyncEngine.h
//
//#import <Foundation/Foundation.h>
//@interface SyncEngine : NSObject
//
//@property (nonatomic, assign) BOOL submitPending;
//@property (nonatomic, assign) BOOL downloadUnits;
//
//- (void)startWithProgress:(SyncProgressBlock)progress
// completion:(SyncCompletionBlock)completion;
//
//@end
//
//// SyncEngine.mm
//
//#import "SyncEngine.h"
//#import "APIClient.h"
//#import "NetworkManager.h"
//
//@interface SyncEngine ()
//
//// Callbacks
//@property (nonatomic, copy) SyncProgressBlock progressBlock;
//@property (nonatomic, copy) SyncCompletionBlock completionBlock;
//
//// Progress tracking
//@property (nonatomic, assign) NSInteger currentStep;
//@property (nonatomic, assign) NSInteger totalSteps;
//
//@end
//
//@implementation SyncEngine
//
//#pragma mark - Public Entry Point
//
//- (void)startWithProgress:(SyncProgressBlock)progress
// completion:(SyncCompletionBlock)completion {
//
// self.progressBlock = progress;
// self.completionBlock = completion;
//
// self.currentStep = 0;
// self.totalSteps = [self calculateTotalSteps];
//
// [self stepCheckNetwork];
//}
//
//#pragma mark - Step Count
//
//- (NSInteger)calculateTotalSteps {
// NSInteger steps = 1; // check network
//
// if (self.submitPending) {
// steps += 1; // submit pending
// }
//
// if (self.downloadUnits) {
// steps += 1; // download data
// }
//
// steps += 1; // finalize
//
// return steps;
//}
//
//#pragma mark - Step 1: Network Check
//
//- (void)stepCheckNetwork {
// [self reportProgress:@"Checking network"];
//
// if (![NetworkManager.sharedManager isConnected]) {
// NSError *error =
// [NSError errorWithDomain:@"Sync"
// code:-1009
// userInfo:@{
// NSLocalizedDescriptionKey :
// @"No internet connection"
// }];
// [self finish:NO error:error];
// return;
// }
//
// if (self.submitPending) {
// [self stepSubmitPending];
// } else if (self.downloadUnits) {
// [self stepDownloadCommonAreas];
// } else {
// [self stepFinalize];
// }
//}
//
//#pragma mark - Step 2: Submit Pending Offline Items
//
//- (void)stepSubmitPending {
// [self reportProgress:@"Submitting pending items"];
//
// __weak typeof(self) weakSelf = self;
//
// [self submitPendingItemsWithCompletion:^(BOOL success, NSError *error) {
// __strong typeof(weakSelf) self = weakSelf;
//
// if (!success) {
// [self finish:NO error:error];
// return;
// }
//
// if (self.downloadUnits) {
// [self stepDownloadCommonAreas];
// } else {
// [self stepFinalize];
// }
// }];
//}
//
//#pragma mark - Step 3: Download Data
//
//- (void)stepDownloadCommonAreas {
// [self reportProgress:@"Downloading common areas"];
//
// __weak typeof(self) weakSelf = self;
//
// [APIClient fetchCommonArea:^(NSDictionary *data, NSError *error) {
// __strong typeof(weakSelf) self = weakSelf;
//
// if (error) {
// [self finish:NO error:error];
// return;
// }
//
// [self persistCommonAreas:data];
// [self stepFinalize];
// }];
//}
//
//#pragma mark - Step 4: Finalize
//
//- (void)stepFinalize {
// [self reportProgress:@"Finalizing sync"];
// [self finalizeSync];
// [self finish:YES error:nil];
//}
//
//#pragma mark - Progress & Completion Helpers
//
//- (void)reportProgress:(NSString *)message {
// self.currentStep++;
//
// if (self.progressBlock) {
// self.progressBlock(self.currentStep,
// self.totalSteps,
// message);
// }
//}
//
//- (void)finish:(BOOL)success error:(NSError *)error {
// if (self.completionBlock) {
// self.completionBlock(success, error);
// }
//
// // Clean up references
// self.progressBlock = nil;
// self.completionBlock = nil;
//}
//
//#pragma mark - Internal Hooks (Implement These)
//
//- (void)submitPendingItemsWithCompletion:(void (^)(BOOL success, NSError *error))completion {
// // TODO:
// // - Query offline table
// // - Upload ONE item at a time
// // - Update local DB on success/failure
// // - Recursively continue until empty
// // - Call completion when done
//}
//
//- (void)persistCommonAreas:(NSDictionary *)data {
// // TODO:
// // Save common areas into local storage / DB
//}
//
//- (void)finalizeSync {
// // TODO:
// // - Update last sync timestamp
// // - Persist sync success state
//}
//
//@end
// SyncHistoryViewController.mm
#import "SyncHistoryViewController.h"
#import "OfflineSyncManager.h"
typedef NS_ENUM(NSInteger, HistorySyncStatus) {
HistorySyncStatusSuccess,
......@@ -14,6 +15,7 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
@property (nonatomic, strong) NSString *uploadedOn;
@property (nonatomic, strong) NSString *actionMade;
@property (nonatomic, assign) HistorySyncStatus status;
@property (nonatomic, strong) NSDictionary *raw;
@end
@implementation HistorySyncItem
......@@ -139,7 +141,6 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
@property (nonatomic, strong) NSArray<HistorySyncItem *> *filteredItems;
@property (nonatomic, assign) NSInteger selectedTab;
@end
@implementation SyncHistoryViewController
......@@ -157,7 +158,13 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
[self setupEmptyState];
[self setupBottomButton];
[self loadMockData];
[self loadHistoryData];
[self applyFilter];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self loadHistoryData];
[self applyFilter];
}
......@@ -185,18 +192,18 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.titleLabel];
self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
[self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
self.shareButton.layer.borderWidth = 0.5;
self.shareButton.layer.cornerRadius = 14;
[self.shareButton addTarget:self
action:@selector(onShare)
forControlEvents:UIControlEventTouchUpInside];
self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.shareButton];
// self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
// [self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
// [self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
// self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
// self.shareButton.layer.borderWidth = 0.5;
// self.shareButton.layer.cornerRadius = 14;
// [self.shareButton addTarget:self
// action:@selector(onShare)
// forControlEvents:UIControlEventTouchUpInside];
// self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
// self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
// [self.headerView addSubview:self.shareButton];
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
......@@ -212,10 +219,10 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
[self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.heightAnchor constraintEqualToConstant:28],
[self.shareButton.widthAnchor constraintEqualToConstant:120],
// [self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
// [self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
// [self.shareButton.heightAnchor constraintEqualToConstant:28],
// [self.shareButton.widthAnchor constraintEqualToConstant:120],
]];
}
......@@ -312,6 +319,43 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
]];
}
#pragma mark - Data
- (void)loadHistoryData {
NSArray *sections =
[[OfflineSyncManager shared] historyItemsForUI];
[self dumpHistoryToFile:sections];
NSMutableArray *items = [NSMutableArray array];
for (NSDictionary *section in sections) {
NSArray *rows = section[@"items"];
for (NSDictionary *row in rows) {
HistorySyncItem *item = [HistorySyncItem new];
item.unitName = row[@"unitName"];
item.createdBy = row[@"createdBy"];
item.createdOn = row[@"createdOn"];
item.uploadedOn = row[@"uploadedOn"];
item.actionMade = row[@"type"];
NSString *status = row[@"status"];
item.status =
[status isEqualToString:@"FAILED"]
? HistorySyncStatusFailed
: HistorySyncStatusSuccess;
item.raw = row;
[items addObject:item];
}
}
self.allItems = items;
}
// Dummy data
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.filteredItems.count;
......@@ -384,6 +428,10 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
[self.syncAgainButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.syncAgainButton.enabled = NO;
[self.syncAgainButton addTarget:self
action:@selector(onSyncAgain)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.syncAgainButton];
[NSLayoutConstraint activateConstraints:@[
......@@ -472,5 +520,45 @@ typedef NS_ENUM(NSInteger, HistorySyncStatus) {
[self.tableView reloadData];
}
- (void)onSyncAgain {
for (HistorySyncItem *item in self.allItems) {
if (item.status == HistorySyncStatusFailed) {
[[OfflineSyncManager shared] retryHistoryItem:item.raw];
}
}
NSLog(@"Starting sync again");
// [[OfflineSyncManager shared] startManualSync];
[self loadHistoryData];
[self applyFilter];
}
- (void)dumpHistoryToFile:(id)history {
NSString *docDir =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES).firstObject;
NSString *path =
[docDir stringByAppendingPathComponent:@"sync_history_dump.txt"];
NSString *content =
[NSString stringWithFormat:@"=== SYNC HISTORY DUMP ===\n%@\n",
history];
NSError *error = nil;
BOOL success =
[content writeToFile:path
atomically:YES
encoding:NSUTF8StringEncoding
error:&error];
if (success) {
NSLog(@"📄 History dumped to: %@", path);
} else {
NSLog(@"❌ Failed to dump history: %@", error);
}
}
@end
......@@ -195,18 +195,18 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.titleLabel];
self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
[self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
self.shareButton.layer.borderWidth = 0.5;
self.shareButton.layer.cornerRadius = 14;
[self.shareButton addTarget:self
action:@selector(onShare)
forControlEvents:UIControlEventTouchUpInside];
self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.shareButton];
// self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
// [self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
// [self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
// self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
// self.shareButton.layer.borderWidth = 0.5;
// self.shareButton.layer.cornerRadius = 14;
// [self.shareButton addTarget:self
// action:@selector(onShare)
// forControlEvents:UIControlEventTouchUpInside];
// self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
// self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
// [self.headerView addSubview:self.shareButton];
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
......@@ -222,10 +222,10 @@ typedef NS_ENUM(NSInteger, SyncPendingViewMode) {
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
[self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.shareButton.heightAnchor constraintEqualToConstant:28],
[self.shareButton.widthAnchor constraintEqualToConstant:120],
// [self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
// [self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
// [self.shareButton.heightAnchor constraintEqualToConstant:28],
// [self.shareButton.widthAnchor constraintEqualToConstant:120],
]];
}
......
......@@ -14,7 +14,7 @@ typedef NS_ENUM(NSInteger, SyncProjectScreenState) {
static NSString * const kSyncSelectedUnitsKey = @"SYNC_SELECTEDUNITS";
static NSString * const kProjectListKey = @"PROJECT_LIST";
@interface SyncUnit : NSObject
@interface SyncUnit : NSObject <NSSecureCoding>
@property (nonatomic, strong) NSString *planId;
@property (nonatomic, strong) NSString *displayName;
@property (nonatomic, strong) NSDictionary *project;
......@@ -24,6 +24,33 @@ static NSString * const kProjectListKey = @"PROJECT_LIST";
@end
@implementation SyncUnit
+ (BOOL)supportsSecureCoding {
return YES;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.planId forKey:@"planId"];
[coder encodeObject:self.displayName forKey:@"displayName"];
[coder encodeObject:self.project forKey:@"project"];
[coder encodeObject:self.projectId forKey:@"projectId"];
[coder encodeObject:self.projectName forKey:@"projectName"];
[coder encodeBool:self.selected forKey:@"selected"];
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
_planId = [coder decodeObjectOfClass:[NSString class] forKey:@"planId"];
_displayName = [coder decodeObjectOfClass:[NSString class] forKey:@"displayName"];
_project = [coder decodeObjectOfClass:[NSDictionary class] forKey:@"project"];
_projectId = [coder decodeObjectOfClass:[NSString class] forKey:@"projectId"];
_projectName = [coder decodeObjectOfClass:[NSString class] forKey:@"projectName"];
_selected = [coder decodeBoolForKey:@"selected"];
}
return self;
}
@end
@interface SyncProject : NSObject
......@@ -445,15 +472,15 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
return;
}
NSLog(@"🌐 No cached PROJECT_LIST, fetching from API");
[self fetchProjectList];
NSLog(@"🌐 No cached PROJECT_LIST, requesting from API");
[self requestProjectList];
}
- (void)fetchProjectList {
- (void)requestProjectList {
[self showLoading:YES];
[APIClient fetchProjectList:^(NSDictionary *data, NSError *error) {
[APIClient requestProjectList:^(NSDictionary *data, NSError *error) {
// debug
NSString *plainText = [NSString stringWithFormat:@"%@", data];
......@@ -648,8 +675,11 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
- (void)onDone {
NSLog(@"Selected units count: %lu",
(unsigned long)self.selectedUnits.count);
[LocalStorage saveArray:self.selectedUnits
forKey:@"SELECTED_OFFLINE_UNITS"];
NSMutableArray *dictArray = [NSMutableArray array];
for (SyncUnit *unit in self.selectedUnits) {
[dictArray addObject:[self dictionaryFromUnit:unit]];
}
[LocalStorage saveArray:dictArray forKey:@"SELECTED_OFFLINE_UNITS"];
[self showOfflineUnit];
}
......
......@@ -5,8 +5,8 @@
#import "SyncHistoryViewController.h"
#import "SyncPendingViewController.h"
#import "SyncProjectViewController.h"
#import "SyncEngine.h"
#import "LocalStorage.h"
#import "OfflineSyncManager.h"
typedef NS_ENUM(NSInteger, SyncCardType) {
SyncCardTypeOfflineUnits = 1,
......@@ -14,6 +14,8 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
SyncCardTypeHistory
};
static NSString * const kLastOfflineSyncDateKey = @"LAST_OFFLINE_SYNC_DATE";
@interface SyncScreenViewController ()
@property (nonatomic, strong) UIView *headerView;
......@@ -71,7 +73,7 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
self.isSyncing = NO;
//placeholders
self.pendingItemCount = 0;
self.pendingItemCount = 1;
self.offlineUnitCount = 1;
self.historyCount = 1;
......@@ -87,6 +89,7 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
self.pendingItemCount = [self loadPendingItemCount];
self.offlineUnitCount = [self loadOfflineUnitCount];
self.historyCount = [self loadHistoryItemCount];
[self refreshUI];
}
......@@ -126,18 +129,9 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
}
- (void)updateLastUpdatedLabel {
if (!self.lastUpdatedDate) {
self.lastUpdatedLabel.text = @"Last Updated:\n--";
return;
}
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateStyle = NSDateFormatterMediumStyle;
fmt.timeStyle = NSDateFormatterShortStyle;
NSString *dateString = [self lastSyncDisplayString];
self.lastUpdatedLabel.text =
[NSString stringWithFormat:@"Last Updated:\n%@",
[fmt stringFromDate:self.lastUpdatedDate]];
[NSString stringWithFormat:@"Last Updated:\n%@", dateString];
}
#pragma mark - Header
......@@ -500,7 +494,6 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
}
- (void)onOfflineUnitsTapped {
if (self.offlineUnitCount == 0) return;
NSLog(@"Offline Units tapped");
SyncProjectViewController *nextVC = [[SyncProjectViewController alloc] init];
......@@ -570,39 +563,48 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
[self refreshUI];
[self showProgressOverlay];
// SyncEngine *engine = [SyncEngine new];
// engine.submitPending = self.shouldSubmitPending;
// engine.downloadUnits = self.shouldDownloadUnits;
//
// __weak typeof(self) weakSelf = self;
//
// [engine startWithProgress:^(NSInteger step,
// NSInteger total,
// NSString *title) {
//
// weakSelf.progressLabel.text =
// [NSString stringWithFormat:@"%@ (%ld/%ld)",
// title, (long)step, (long)total];
//
// weakSelf.progressBar.progress =
// (float)step / (float)total;
//
// } completion:^(BOOL success, NSError *error) {
//
// [weakSelf.syncProgressOverlay removeFromSuperview];
// weakSelf.syncProgressOverlay = nil;
//
// weakSelf.isSyncing = NO;
//
// if (success) {
// weakSelf.lastUpdatedDate = [NSDate date];
// } else {
// NSLog(@"❌ Sync failed: %@", error.localizedDescription);
// // TODO: show alert
// }
//
// [weakSelf refreshUI];
// }];
__weak typeof(self) weakSelf = self;
// 1️⃣ Manual pending sync
if (self.shouldSubmitPending) {
NSLog(@"Syncing Pending Items");
[[OfflineSyncManager shared]
processNextItemWithProgress:^(NSInteger step, NSInteger total, NSString *title) {
self.progressLabel.text =
[NSString stringWithFormat:@"%ld / %ld", step, total];
self.titleLabel.text = title;
self.progressBar.progress =
total > 0 ? (float)step / (float)total : 0;
} completion:^(BOOL finished) {
self.pendingItemCount = [self loadPendingItemCount];
self.historyCount = [self loadHistoryItemCount];
[self refreshUI];
}];
}
// 2️⃣ Unit + image download sync
if (self.shouldDownloadUnits) {
NSLog(@"Downloading Units");
[[OfflineSyncManager shared]
startDownloadUnitImagesWithProgress:^(NSInteger completed, NSInteger total) {
weakSelf.progressLabel.text =
[NSString stringWithFormat:@"Downloading Units (%ld/%ld)",
(long)completed, (long)total];
weakSelf.progressBar.progress =
total > 0 ? (float)completed / (float)total : 0;
} completion:^(BOOL success) {
[weakSelf finishSyncWithSuccess:success];
}];
}
}
- (void)dismissSyncModal {
......@@ -630,4 +632,38 @@ typedef NS_ENUM(NSInteger, SyncCardType) {
return units.count;
}
- (NSInteger)loadHistoryItemCount {
NSArray *units = [LocalStorage loadArrayForKey:@"SYNC_HISTORY_QUEUE"];
return units.count;
}
- (void)finishSyncWithSuccess:(BOOL)success {
[self.syncProgressOverlay removeFromSuperview];
self.syncProgressOverlay = nil;
self.isSyncing = NO;
if (success) {
self.lastUpdatedDate = [NSDate date];
}
[self refreshUI];
}
- (NSString *)lastSyncDisplayString {
NSNumber *ts = [LocalStorage loadObjectForKey:kLastOfflineSyncDateKey];
if (!ts) {
return @"--";
}
NSDate *date = [NSDate dateWithTimeIntervalSince1970:ts.doubleValue];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateStyle = NSDateFormatterMediumStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
return [formatter stringFromDate:date];
}
@end
......@@ -6,12 +6,12 @@ NS_ASSUME_NONNULL_BEGIN
@interface APIClient : NSObject
+ (void)fetchAccessItem:(NSString *)unitId
+ (void)requestAccessItem:(NSString *)unitId
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion;
+ (void)fetchGetUnitPlan:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestGetUnitPlan:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchSettingsByLocation:(NSString * _Nonnull)locationID
+ (void)requestSettingsByLocation:(NSString * _Nonnull)locationID
projectID:(NSString * _Nonnull)projectID
completion:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
......@@ -23,9 +23,9 @@ NS_ASSUME_NONNULL_BEGIN
images:(NSArray<UIImage *> * _Nullable)images
completion:(void (^)(NSDictionary * _Nullable response, NSError * _Nullable error))completion;
+ (void)fetchAppointment:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestAppointment:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchGeneralInfo:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestGeneralInfo:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)submitAppointment:(NSDictionary *)appointmentData
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion;
......@@ -33,15 +33,15 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)submitRepresentativeAppointment:(NSDictionary *)repData
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion;
+ (void)fetchCancelAppointment:(id)appointmentId
+ (void)requestCancelAppointment:(id)appointmentId
reason:(NSString *)reason
completion:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchDashboardInfo:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)requestDashboardInfo:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchAnnouncement:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)requestAnnouncement:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchHistory:(NSString *)issueID
+ (void)requestHistory:(NSString *)issueID
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+(void)submitAddInfo:(NSString *)issueID
......@@ -55,23 +55,29 @@ NS_ASSUME_NONNULL_BEGIN
mediaType:(NSString *)mediaType
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchIssues:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)requestIssues:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchVoidIssue:(id)issueID
+ (void)requestVoidIssue:(id)issueID
remarks:(NSString *)remarks
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchDeleteIssue:(id)issueID
+ (void)requestDeleteIssue:(id)issueID
remarks:(NSString *)remarks
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchCommonArea:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestCommonArea:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchGeneralSettings:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestGeneralSettings:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchDefectMatrix:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestDefectMatrix:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)fetchProjectList:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestProjectList:(void (^)(NSDictionary * _Nullable data, NSError * _Nullable error))completion;
+ (void)requestArrayImage:(NSArray *)imageArray
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)downloadAndCacheImage:(NSURL *)url
completion:(void (^)(BOOL success))completion;
@end
......
......@@ -18,4 +18,8 @@
/// Save array safely (for convenience)
+ (void)saveArray:(NSArray *)array forKey:(NSString *)key;
+ (NSDictionary *)loadDictionaryForKey:(NSString *)key;
+ (void)saveDictionary:(NSDictionary *)dict forKey:(NSString *)key;
@end
......@@ -57,4 +57,16 @@
[self saveObject:array forKey:key];
}
+ (NSDictionary *)loadDictionaryForKey:(NSString *)key {
id object = [self loadObjectForKey:key];
if ([object isKindOfClass:[NSDictionary class]]) {
return object;
}
return nil;
}
+ (void)saveDictionary:(NSDictionary *)dict forKey:(NSString *)key {
[self saveObject:dict forKey:key];
}
@end
......@@ -28,9 +28,22 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)hasPendingItems;
- (NSArray *)pendingItemsForUI;
- (NSArray *)historyItemsForUI;
- (void)clearOfflineQueue;
- (void)processNextItemWithProgress:(void (^)(NSInteger step,
NSInteger total,
NSString *title))progress
completion:(void (^)(BOOL finished))completion;
// Retry failed history item
- (void)retryHistoryItem:(NSDictionary *)historyItem;
// Download Units
- (void)startDownloadUnitImagesWithProgress:(void (^)(NSInteger completed, NSInteger total))progress
completion:(void (^)(BOOL success))completion;
@end
NS_ASSUME_NONNULL_END
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment