Commit d5fc7ec0 authored by Wei Han's avatar Wei Han

code update

parent 01266f51
...@@ -8,22 +8,22 @@ ...@@ -8,22 +8,22 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
1EE3505D2884B35517284FC0 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA1877716B752590ECD37293 /* libPods-example.a */; };
44006126336D83DB220E7214 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; 44006126336D83DB220E7214 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
A9347BA1DEB0869A7449D25A /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 62D3056EB1529798F78D8AAE /* libPods-example.a */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
08A8F0EC3E4A7E9111ABA675 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = "<group>"; };
13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; }; 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
5C8BADDA6881DBD3E3FFBD0E /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = "<group>"; }; 378A4C515FDC6061AD68C42E /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; };
62D3056EB1529798F78D8AAE /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = example/AppDelegate.swift; sourceTree = "<group>"; }; 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = example/AppDelegate.swift; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = "<group>"; };
9C044A90156FCEF85786783C /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = "<group>"; }; DA1877716B752590ECD37293 /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A9347BA1DEB0869A7449D25A /* libPods-example.a in Frameworks */, 1EE3505D2884B35517284FC0 /* libPods-example.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
62D3056EB1529798F78D8AAE /* libPods-example.a */, DA1877716B752590ECD37293 /* libPods-example.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -92,8 +92,8 @@ ...@@ -92,8 +92,8 @@
BBD78D7AC51CEA395F1C20DB /* Pods */ = { BBD78D7AC51CEA395F1C20DB /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
9C044A90156FCEF85786783C /* Pods-example.debug.xcconfig */, 378A4C515FDC6061AD68C42E /* Pods-example.debug.xcconfig */,
5C8BADDA6881DBD3E3FFBD0E /* Pods-example.release.xcconfig */, 08A8F0EC3E4A7E9111ABA675 /* Pods-example.release.xcconfig */,
); );
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -105,13 +105,13 @@ ...@@ -105,13 +105,13 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
buildPhases = ( buildPhases = (
309150C9AAFDB30830CFACCC /* [CP] Check Pods Manifest.lock */, E149C963790203E4728E183B /* [CP] Check Pods Manifest.lock */,
13B07F871A680F5B00A75B9A /* Sources */, 13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */, 13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
82D720B7A901D1E9C13BE9D2 /* [CP] Embed Pods Frameworks */, 1F9BDF608EDC73376B321887 /* [CP] Embed Pods Frameworks */,
9C3136C3E0FC26587EC44C8F /* [CP] Copy Pods Resources */, ADC23F2AA84D12028019349F /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
...@@ -183,60 +183,60 @@ ...@@ -183,60 +183,60 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
}; };
309150C9AAFDB30830CFACCC /* [CP] Check Pods Manifest.lock */ = { 1F9BDF608EDC73376B321887 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist",
); );
inputPaths = ( name = "[CP] Embed Pods Frameworks";
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = ( outputFileListPaths = (
); "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist",
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
82D720B7A901D1E9C13BE9D2 /* [CP] Embed Pods Frameworks */ = { ADC23F2AA84D12028019349F /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Embed Pods Frameworks"; name = "[CP] Copy Pods Resources";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist", "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
9C3136C3E0FC26587EC44C8F /* [CP] Copy Pods Resources */ = { E149C963790203E4728E183B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
); );
inputFileListPaths = ( inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist",
); );
name = "[CP] Copy Pods Resources"; inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = ( outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist", );
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt",
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n"; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
...@@ -255,7 +255,7 @@ ...@@ -255,7 +255,7 @@
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = { 13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 9C044A90156FCEF85786783C /* Pods-example.debug.xcconfig */; baseConfigurationReference = 378A4C515FDC6061AD68C42E /* Pods-example.debug.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
...@@ -283,7 +283,7 @@ ...@@ -283,7 +283,7 @@
}; };
13B07F951A680F5B00A75B9A /* Release */ = { 13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 5C8BADDA6881DBD3E3FFBD0E /* Pods-example.release.xcconfig */; baseConfigurationReference = 08A8F0EC3E4A7E9111ABA675 /* Pods-example.release.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
......
// DashboardViewController.h // DashboardViewController.h
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import "DrawerController.h"
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
...@@ -8,6 +9,11 @@ NS_ASSUME_NONNULL_BEGIN ...@@ -8,6 +9,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, copy) NSString *ClientID; @property (nonatomic, copy) NSString *ClientID;
@property (nonatomic, copy) NSString *ClientCode; @property (nonatomic, copy) NSString *ClientCode;
@property (nonatomic, copy) NSString *user_token; @property (nonatomic, copy) NSString *user_token;
@property (nonatomic, weak) DrawerController *drawerController;
- (instancetype)initWithClientID:(NSString *)clientID
clientCode:(NSString *)clientCode
userToken:(NSString *)userToken;
@end @end
......
...@@ -49,6 +49,18 @@ ...@@ -49,6 +49,18 @@
CGFloat _currentY; CGFloat _currentY;
} }
- (instancetype)initWithClientID:(NSString *)clientID
clientCode:(NSString *)clientCode
userToken:(NSString *)userToken {
self = [super initWithNibName:nil bundle:nil];
if (self) {
_ClientID = [clientID copy];
_ClientCode = [clientCode copy];
_user_token = [userToken copy];
}
return self;
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
...@@ -61,8 +73,9 @@ ...@@ -61,8 +73,9 @@
self.projectCode = @"PTD197656"; self.projectCode = @"PTD197656";
self.projectName = @"Ara E`Residence Dev"; self.projectName = @"Ara E`Residence Dev";
[self refreshDashboardContent]; [self checkAndRefreshAPIs];
NSLog(@"in viewDidLoad ClientID: %@, ClientCode: %@, user_token: %@", self.ClientID, self.ClientCode, self.user_token); NSLog(@"in viewDidLoad ClientID: %@, ClientCode: %@, user_token: %@", self.ClientID, self.ClientCode, self.user_token);
NSLog(@"dashboard.drawerController = %@", self.drawerController);
} }
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
...@@ -73,6 +86,16 @@ ...@@ -73,6 +86,16 @@
NSLog(@"in viewWillAppear ClientID: %@, ClientCode: %@, user_token: %@", self.ClientID, self.ClientCode, self.user_token); NSLog(@"in viewWillAppear ClientID: %@, ClientCode: %@, user_token: %@", self.ClientID, self.ClientCode, self.user_token);
} }
- (void)checkAndRefreshAPIs {
// Only trigger API calls when all props are set and not the placeholder
if (![_ClientID isEqualToString:@"clientID_loading"] &&
![_ClientCode isEqualToString:@"clientCode_loading"] &&
![_user_token isEqualToString:@"userToken_loading"]) {
NSLog(@"in checkAndRefreshApis ClientID: %@, ClientCode: %@, user_token: %@", self.ClientID, self.ClientCode, self.user_token);
[self refreshDashboardContent]; // Your API call method
}
}
#pragma mark - Refresh Logic #pragma mark - Refresh Logic
- (void)refreshDashboardContent { - (void)refreshDashboardContent {
NSLog(@"🔁 Refreshing dashboard content..."); NSLog(@"🔁 Refreshing dashboard content...");
...@@ -204,6 +227,21 @@ ...@@ -204,6 +227,21 @@
[self.projectNameLabel.centerXAnchor constraintEqualToAnchor:headerBar.centerXAnchor], [self.projectNameLabel.centerXAnchor constraintEqualToAnchor:headerBar.centerXAnchor],
[self.projectNameLabel.centerYAnchor constraintEqualToAnchor:headerBar.centerYAnchor] [self.projectNameLabel.centerYAnchor constraintEqualToAnchor:headerBar.centerYAnchor]
]]; ]];
// --- Menu Button (Top Right) ---
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
menuButton.translatesAutoresizingMaskIntoConstraints = NO;
[menuButton setImage:[UIImage systemImageNamed:@"line.horizontal.3"] forState:UIControlStateNormal];
menuButton.tintColor = UIColor.whiteColor;
[menuButton addTarget:self action:@selector(handleMenuButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[headerBar addSubview:menuButton];
[NSLayoutConstraint activateConstraints:@[
[menuButton.trailingAnchor constraintEqualToAnchor:headerBar.trailingAnchor constant:-16],
[menuButton.centerYAnchor constraintEqualToAnchor:headerBar.centerYAnchor],
[menuButton.widthAnchor constraintEqualToConstant:26],
[menuButton.heightAnchor constraintEqualToConstant:26],
]];
// ----------------------- // -----------------------
// Unit name bottom-left // Unit name bottom-left
...@@ -265,10 +303,6 @@ ...@@ -265,10 +303,6 @@
} }
} }
- (void)handleMenuButtonTapped {
NSLog(@"🍔 Menu button tapped");
}
#pragma mark - Footer #pragma mark - Footer
- (void)setupFooter { - (void)setupFooter {
CGFloat footerHeight = 80.0; CGFloat footerHeight = 80.0;
...@@ -1206,4 +1240,29 @@ ...@@ -1206,4 +1240,29 @@
self.spinner = nil; self.spinner = nil;
} }
- (void)handleMenuButtonTapped {
NSLog(@"🍔 Menu button tapped");
if (self.drawerController) {
[self.drawerController toggleDrawer];
} else {
NSLog(@"⚠️ drawerController not set on DashboardViewController");
}
}
#pragma mark - prop setter
- (void)setClientID:(NSString *)ClientID {
_ClientID = [ClientID copy];
[self checkAndRefreshAPIs];
}
- (void)setClientCode:(NSString *)ClientCode {
_ClientCode = [ClientCode copy];
[self checkAndRefreshAPIs];
}
- (void)setUser_token:(NSString *)user_token {
_user_token = [user_token copy];
[self checkAndRefreshAPIs];
}
@end @end
// DrawerController.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString * const DrawerDidSelectItemNotification; // posted when an item is tapped
@interface DrawerController : UIViewController
@property (nonatomic, strong, readonly) UIViewController *mainViewController;
@property (nonatomic, strong, readonly) UIViewController *drawerViewController;
// ✅ New initializer: pass drawer + client props directly
- (instancetype)initWithDrawerViewController:(UIViewController *)drawer
clientID:(NSString *)clientID
clientCode:(NSString *)clientCode
userToken:(NSString *)user_token;
// Drawer actions
- (void)openDrawer;
- (void)closeDrawer;
- (void)toggleDrawer;
- (BOOL)isDrawerOpen;
// Optional: keep setters if props can change later
@property (nonatomic, copy) NSString *ClientID;
@property (nonatomic, copy) NSString *ClientCode;
@property (nonatomic, copy) NSString *user_token;
@end
NS_ASSUME_NONNULL_END
// DrawerController.m
#import "DrawerController.h"
#import "DashboardViewController.h"
NSString * const DrawerDidSelectItemNotification = @"DrawerDidSelectItemNotification";
@interface DrawerController () <UIGestureRecognizerDelegate>
@property (nonatomic, strong) DashboardViewController *mainVC;
@property (nonatomic, strong) UIViewController *drawerVC;
@property (nonatomic, strong) UIView *overlayView;
@property (nonatomic, assign) BOOL drawerOpen;
@property (nonatomic, assign) CGFloat drawerWidth;
@property (nonatomic, strong) UIPanGestureRecognizer *panGR;
@property (nonatomic, strong) NSLayoutConstraint *drawerLeadingConstraint;
@end
@implementation DrawerController
#pragma mark - Initializer
- (instancetype)initWithDrawerViewController:(UIViewController *)drawer
clientID:(NSString *)clientID
clientCode:(NSString *)clientCode
userToken:(NSString *)user_token {
self = [super initWithNibName:nil bundle:nil];
if (!self) return nil;
// 1️⃣ Initialize DashboardViewController with props
_mainVC = [[DashboardViewController alloc] initWithClientID:clientID
clientCode:clientCode
userToken:user_token];
// 2️⃣ Set back-reference to drawerController
_mainVC.drawerController = self;
// 3️⃣ Save props locally
_ClientID = [clientID copy];
_ClientCode = [clientCode copy];
_user_token = [user_token copy];
// 4️⃣ Set drawer VC and drawer width
_drawerVC = drawer;
_drawerWidth = MIN([UIScreen mainScreen].bounds.size.width * 0.78, 360);
return self;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor blackColor];
[self setupDrawer];
[self setupOverlay];
[self setupMainVC];
[self setupPanGesture];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(menuItemSelected:)
name:DrawerDidSelectItemNotification
object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Getters
- (UIViewController *)mainViewController {
return _mainVC;
}
- (UIViewController *)drawerViewController {
return _drawerVC;
}
#pragma mark - Setup UI
- (void)setupDrawer {
[self addChildViewController:self.drawerVC];
self.drawerVC.view.translatesAutoresizingMaskIntoConstraints = NO;
self.drawerVC.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.drawerVC.view];
[self.drawerVC didMoveToParentViewController:self];
self.drawerLeadingConstraint =
[self.drawerVC.view.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:-self.drawerWidth];
[self.drawerVC.view.widthAnchor constraintEqualToConstant:self.drawerWidth].active = YES;
[self.drawerVC.view.topAnchor constraintEqualToAnchor:self.view.topAnchor].active = YES;
[self.drawerVC.view.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES;
self.drawerLeadingConstraint.active = YES;
}
- (void)setupOverlay {
// Overlay only covers the mainVC, not the drawer
self.overlayView = [[UIView alloc] initWithFrame:self.mainVC.view.frame];
self.overlayView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
self.overlayView.alpha = 0.0;
self.overlayView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// Tap gesture to close drawer
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeDrawer)];
[self.overlayView addGestureRecognizer:tap];
// Add overlay **below** the drawer so it doesn't block menu interactions
[self.view insertSubview:self.overlayView belowSubview:self.drawerVC.view];
}
- (void)setupMainVC {
[self addChildViewController:self.mainVC];
self.mainVC.view.frame = self.view.bounds;
self.mainVC.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.mainVC.view];
[self.mainVC didMoveToParentViewController:self];
}
- (void)setupPanGesture {
self.panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
self.panGR.delegate = self;
[self.mainVC.view addGestureRecognizer:self.panGR];
}
#pragma mark - Drawer Actions
- (void)openDrawer {
// Make sure overlay and drawer are on top
[self.view bringSubviewToFront:self.overlayView];
[self.view bringSubviewToFront:self.drawerVC.view];
self.drawerLeadingConstraint.constant = 0;
[UIView animateWithDuration:0.25 animations:^{
[self.view layoutIfNeeded];
self.overlayView.alpha = 1.0;
}];
self.drawerOpen = YES;
}
- (void)closeDrawer {
self.drawerLeadingConstraint.constant = -self.drawerWidth;
[UIView animateWithDuration:0.25 animations:^{
[self.view layoutIfNeeded];
self.overlayView.alpha = 0.0;
}];
self.drawerOpen = NO;
}
- (void)toggleDrawer {
if (self.drawerOpen) [self closeDrawer];
else [self openDrawer];
}
- (BOOL)isDrawerOpen {
return self.drawerOpen;
}
#pragma mark - Pan Gesture
- (void)handlePan:(UIPanGestureRecognizer *)pan {
CGPoint translation = [pan translationInView:self.view];
CGFloat x = translation.x;
static CGFloat startX;
if (pan.state == UIGestureRecognizerStateBegan) {
startX = self.mainVC.view.transform.tx;
} else if (pan.state == UIGestureRecognizerStateChanged) {
CGFloat newTx = startX + x;
newTx = MAX(0, newTx);
newTx = MIN(self.drawerWidth, newTx);
CGFloat progress = newTx / self.drawerWidth;
self.mainVC.view.transform = CGAffineTransformMakeTranslation(newTx, 0);
self.drawerLeadingConstraint.constant = -self.drawerWidth + newTx;
[self.view layoutIfNeeded];
self.overlayView.alpha = progress;
} else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled) {
CGFloat velocityX = [pan velocityInView:self.view].x;
CGFloat currentTx = self.mainVC.view.transform.tx;
BOOL shouldOpen = NO;
if (fabs(velocityX) > 400) {
shouldOpen = (velocityX > 0);
} else {
shouldOpen = currentTx > (self.drawerWidth * 0.45);
}
if (shouldOpen) [self openDrawer];
else [self closeDrawer];
}
}
#pragma mark - Notification
- (void)menuItemSelected:(NSNotification *)note {
[self closeDrawer];
}
#pragma mark - Gesture Delegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == self.panGR) {
CGPoint v = [self.panGR velocityInView:self.view];
return fabs(v.x) > fabs(v.y);
}
return YES;
}
#pragma mark - Prop Setters
- (void)setClientID:(NSString *)ClientID {
_ClientID = [ClientID copy];
if ([self.mainVC respondsToSelector:NSSelectorFromString(@"setClientID:")]) {
[self.mainVC setValue:_ClientID forKey:@"ClientID"];
}
}
- (void)setClientCode:(NSString *)ClientCode {
_ClientCode = [ClientCode copy];
if ([self.mainVC respondsToSelector:NSSelectorFromString(@"setClientCode:")]) {
[self.mainVC setValue:_ClientCode forKey:@"ClientCode"];
}
}
- (void)setUser_token:(NSString *)user_token {
_user_token = [user_token copy];
if ([self.mainVC respondsToSelector:NSSelectorFromString(@"setUser_token:")]) {
[self.mainVC setValue:_user_token forKey:@"user_token"];
}
}
@end
// DrawerViewController.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface DrawerViewController : UIViewController
// Data to populate (you can set these from GLOBALS or app state)
@property (nonatomic, strong) NSString *profileName;
@property (nonatomic, strong) NSString *profileEmail;
@property (nonatomic, strong) NSURL *profileImageURL;
@property (nonatomic, strong) NSArray<NSDictionary *> *menuItems; // array of { @"title":..., @"action":... }
@end
NS_ASSUME_NONNULL_END
// DrawerViewController.m
#import "DrawerViewController.h"
#import "DrawerController.h"
#import "SyncScreenViewController.h"
@interface DrawerViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UIImageView *avatarView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *emailLabel;
@property (nonatomic, strong) UITableView *table;
@property (nonatomic, strong) UIView *headerContainer;
@end
@implementation DrawerViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:0.02 green:0.36 blue:0.47 alpha:1.0]; // #035E79-ish
[self buildUI];
[self loadDefaultsIfNeeded];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleDrawerAction:)
name:DrawerDidSelectItemNotification
object:nil];
}
- (void)buildUI {
self.view.backgroundColor = [UIColor colorWithRed:0.02 green:0.36 blue:0.47 alpha:1.0];
CGFloat topHeight = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 180 : 120;
// HEADER CONTAINER
self.headerContainer = [[UIView alloc] init];
self.headerContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.headerContainer.backgroundColor = [UIColor colorWithRed:0 green:0.42 blue:0.55 alpha:1.0];
[self.view addSubview:self.headerContainer];
[NSLayoutConstraint activateConstraints:@[
[self.headerContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerContainer.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.headerContainer.heightAnchor constraintEqualToConstant:topHeight],
]];
// TOUCHABLE HEADER
UIButton *profileTap = [UIButton buttonWithType:UIButtonTypeCustom];
profileTap.translatesAutoresizingMaskIntoConstraints = NO;
[profileTap addTarget:self action:@selector(profileTapped) forControlEvents:UIControlEventTouchUpInside];
[self.headerContainer addSubview:profileTap];
[NSLayoutConstraint activateConstraints:@[
[profileTap.leadingAnchor constraintEqualToAnchor:self.headerContainer.leadingAnchor],
[profileTap.trailingAnchor constraintEqualToAnchor:self.headerContainer.trailingAnchor],
[profileTap.topAnchor constraintEqualToAnchor:self.headerContainer.topAnchor],
[profileTap.bottomAnchor constraintEqualToAnchor:self.headerContainer.bottomAnchor],
]];
// AVATAR
CGFloat avatarSize = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? 100 : 50;
self.avatarView = [[UIImageView alloc] init];
self.avatarView.translatesAutoresizingMaskIntoConstraints = NO;
self.avatarView.layer.cornerRadius = avatarSize / 2.0;
self.avatarView.clipsToBounds = YES;
self.avatarView.layer.borderColor = [UIColor whiteColor].CGColor;
self.avatarView.layer.borderWidth = 1.0;
self.avatarView.contentMode = UIViewContentModeScaleAspectFill;
[self.headerContainer addSubview:self.avatarView];
[NSLayoutConstraint activateConstraints:@[
[self.avatarView.leadingAnchor constraintEqualToAnchor:self.headerContainer.leadingAnchor constant:18],
[self.avatarView.centerYAnchor constraintEqualToAnchor:self.headerContainer.centerYAnchor],
[self.avatarView.widthAnchor constraintEqualToConstant:avatarSize],
[self.avatarView.heightAnchor constraintEqualToConstant:avatarSize],
]];
// NAME LABEL
self.nameLabel = [[UILabel alloc] init];
self.nameLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.nameLabel.textColor = UIColor.whiteColor;
self.nameLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightRegular];
self.nameLabel.numberOfLines = 2;
[self.headerContainer addSubview:self.nameLabel];
// EMAIL LABEL
self.emailLabel = [[UILabel alloc] init];
self.emailLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.emailLabel.textColor = UIColor.whiteColor;
self.emailLabel.font = [UIFont systemFontOfSize:14];
[self.headerContainer addSubview:self.emailLabel];
[NSLayoutConstraint activateConstraints:@[
[self.nameLabel.leadingAnchor constraintEqualToAnchor:self.avatarView.trailingAnchor constant:16],
[self.nameLabel.trailingAnchor constraintEqualToAnchor:self.headerContainer.trailingAnchor constant:-18],
[self.nameLabel.bottomAnchor constraintEqualToAnchor:self.headerContainer.centerYAnchor constant:-4],
[self.emailLabel.leadingAnchor constraintEqualToAnchor:self.nameLabel.leadingAnchor],
[self.emailLabel.trailingAnchor constraintEqualToAnchor:self.nameLabel.trailingAnchor],
[self.emailLabel.topAnchor constraintEqualToAnchor:self.nameLabel.bottomAnchor constant:4],
]];
// MENU TABLE
self.table = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.table.translatesAutoresizingMaskIntoConstraints = NO;
self.table.dataSource = self;
self.table.delegate = self;
self.table.backgroundColor = UIColor.clearColor;
self.table.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview:self.table];
[NSLayoutConstraint activateConstraints:@[
[self.table.topAnchor constraintEqualToAnchor:self.headerContainer.bottomAnchor],
[self.table.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.table.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.table.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
]];
}
- (void)loadDefaultsIfNeeded {
if (!self.profileName) self.profileName = @"Guest User";
if (!self.profileEmail) self.profileEmail = @"guest@example.com";
if (!self.profileImageURL) self.profileImageURL = nil;
self.nameLabel.text = self.profileName;
self.emailLabel.text = self.profileEmail;
if (self.profileImageURL) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *d = [NSData dataWithContentsOfURL:self.profileImageURL];
UIImage *img = d ? [UIImage imageWithData:d] : [UIImage imageNamed:@"small_placeholder"];
dispatch_async(dispatch_get_main_queue(), ^{
self.avatarView.image = img;
});
});
} else {
self.avatarView.image = [UIImage imageNamed:@"small_placeholder"];
}
if (!self.menuItems) {
self.menuItems = @[
@{@"title": @"Project List", @"action": @"projectList"},
@{@"title": @"Notification", @"action": @"notification"},
@{@"title": @"Announcement", @"action": @"announcement"},
@{@"title": @"Help", @"action": @"help"},
@{@"title": @"Sync", @"action": @"sync"},
@{@"title": @"Logout", @"action": @"logout"}
];
}
[self.table reloadData];
}
#pragma mark - Profile tap
- (void)profileTapped {
// Post a notification to navigate
[[NSNotificationCenter defaultCenter] postNotificationName:DrawerDidSelectItemNotification object:nil userInfo:@{@"action": @"profile"}];
}
#pragma mark - Table datasource/delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.menuItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = @"drawerCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font = [UIFont systemFontOfSize:16];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSDictionary *item = self.menuItems[indexPath.row];
cell.textLabel.text = item[@"title"] ?: @"";
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 56; }
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *item = self.menuItems[indexPath.row];
NSString *action = item[@"action"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DrawerDidSelectItemNotification"
object:action];
}
- (void)handleDrawerAction:(NSNotification *)notification {
NSString *action = notification.object;
if ([action isEqualToString:@"projectList"]) {
// [self openProjectList];
NSLog(@"navigating to Project List");
}
else if ([action isEqualToString:@"notification"]) {
// [self openNotification];
NSLog(@"navigating to Notification");
}
else if ([action isEqualToString:@"announcement"]) {
// [self openAnnouncement];
NSLog(@"navigating to Announcement");
}
else if ([action isEqualToString:@"help"]) {
// [self openHelp];
NSLog(@"navigating to Help");
}
else if ([action isEqualToString:@"sync"]) {
NSLog(@"navigating to Sync");
SyncScreenViewController *nextVC = [[SyncScreenViewController alloc] init];
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nextVC animated:YES completion:nil];
}
else if ([action isEqualToString:@"logout"]) {
// [self performLogout];
NSLog(@"navigating to Logout");
}
}
@end
//QmsPlugin.mm // QmsPlugin.mm
#import "QmsPlugin.h" #import "QmsPlugin.h"
#import "DashboardViewController.h" #import "DashboardViewController.h"
#import "DrawerViewController.h"
#import "DrawerController.h"
@implementation QmsPluginUI @implementation QmsPluginUI
+ (UIViewController *)makeViewController { + (UIViewController *)makeViewController {
DashboardViewController *vc = [[DashboardViewController alloc] init];
return vc; // 1. Create main dashboard screen (props will be set via DrawerController)
DrawerViewController *drawer = [[DrawerViewController alloc] init];
drawer.profileName = @"placeholder";
drawer.profileEmail = @"placeholder";
// 2. Set client props (replace with actual values from your globals or RN)
NSString *clientID = @"clientID_loading";
NSString *clientCode = @"clientCode_loading";
NSString *userToken = @"userToken_loading";
// 3. Create DrawerController with drawer + props
DrawerController *drawerController =
[[DrawerController alloc] initWithDrawerViewController:drawer
clientID:clientID
clientCode:clientCode
userToken:userToken];
// 4. Allow dashboard to call openDrawer() via drawerController.mainViewController
if ([drawerController.mainViewController isKindOfClass:[DashboardViewController class]]) {
((DashboardViewController *)drawerController.mainViewController).drawerController = drawerController;
}
NSLog(@"drawerController.mainViewController = %@", drawerController.mainViewController);
return drawerController;
} }
@end @end
// SyncViewController.h
#import <UIKit/UIKit.h>
@interface SyncScreenViewController : UIViewController
@end
// SyncViewController.m
#import "SyncScreenViewController.h"
@interface SyncScreenViewController ()
@property (nonatomic, strong) UIView *headerView;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *lastUpdatedLabel;
@property (nonatomic, strong) UIStackView *cardStack;
@property (nonatomic, strong) UIView *offlineUnitCard;
@property (nonatomic, strong) UIView *pendingItemsCard;
@property (nonatomic, strong) UIView *historyCard;
@property (nonatomic, strong) UIButton *syncButton;
@end
@implementation SyncScreenViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
[self setupHeader];
[self setupMainContent];
[self setupSyncButton];
}
#pragma mark - Header
- (void)setupHeader {
self.headerView = [[UIView alloc] init];
self.headerView.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.headerView];
self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.backButton setImage:[UIImage imageNamed:@"back24"] forState:UIControlStateNormal];
self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.backButton];
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.text = @"SYNC";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.font = [UIFont boldSystemFontOfSize:18];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:self.titleLabel];
// Constraints
[NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.headerView.heightAnchor constraintEqualToConstant:48],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:8],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:32],
[self.backButton.heightAnchor constraintEqualToConstant:32],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
]];
}
#pragma mark - Main Content
- (void)setupMainContent {
UIView *content = [[UIView alloc] init];
content.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:content];
[NSLayoutConstraint activateConstraints:@[
[content.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:16],
[content.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[content.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
]];
// Last Updated
self.lastUpdatedLabel = [[UILabel alloc] init];
self.lastUpdatedLabel.numberOfLines = 2;
self.lastUpdatedLabel.text = @"Last Updated:\n--";
self.lastUpdatedLabel.textColor = [UIColor grayColor];
self.lastUpdatedLabel.font = [UIFont boldSystemFontOfSize:16];
self.lastUpdatedLabel.translatesAutoresizingMaskIntoConstraints = NO;
[content addSubview:self.lastUpdatedLabel];
[NSLayoutConstraint activateConstraints:@[
[self.lastUpdatedLabel.topAnchor constraintEqualToAnchor:content.topAnchor],
[self.lastUpdatedLabel.leadingAnchor constraintEqualToAnchor:content.leadingAnchor],
[self.lastUpdatedLabel.trailingAnchor constraintEqualToAnchor:content.trailingAnchor],
]];
// Cards Stack
self.cardStack = [[UIStackView alloc] init];
self.cardStack.axis = UILayoutConstraintAxisVertical;
self.cardStack.spacing = 16;
self.cardStack.translatesAutoresizingMaskIntoConstraints = NO;
[content addSubview:self.cardStack];
[NSLayoutConstraint activateConstraints:@[
[self.cardStack.topAnchor constraintEqualToAnchor:self.lastUpdatedLabel.bottomAnchor constant:16],
[self.cardStack.leadingAnchor constraintEqualToAnchor:content.leadingAnchor],
[self.cardStack.trailingAnchor constraintEqualToAnchor:content.trailingAnchor],
]];
// Add 3 cards
[self.cardStack addArrangedSubview:[self createCardWithTitle:@"Offline Units" count:@"0"]];
[self.cardStack addArrangedSubview:[self createCardWithTitle:@"Pending Items" count:@"0"]];
[self.cardStack addArrangedSubview:[self createCardWithTitle:@"History" count:@"0"]];
}
#pragma mark - Card Factory
- (UIView *)createCardWithTitle:(NSString *)title count:(NSString *)countText {
UIView *card = [[UIView alloc] init];
card.backgroundColor = UIColor.whiteColor;
card.layer.borderWidth = 1;
card.layer.borderColor = [UIColor lightGrayColor].CGColor;
card.layer.cornerRadius = 10;
card.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[card.heightAnchor constraintEqualToConstant:120]
]];
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.text = title;
titleLabel.font = [UIFont boldSystemFontOfSize:20];
titleLabel.textColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
UILabel *countLabel = [[UILabel alloc] init];
countLabel.text = countText;
countLabel.font = [UIFont boldSystemFontOfSize:28];
countLabel.textColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
countLabel.textAlignment = NSTextAlignmentRight;
countLabel.translatesAutoresizingMaskIntoConstraints = NO;
[card addSubview:titleLabel];
[card addSubview:countLabel];
[NSLayoutConstraint activateConstraints:@[
[titleLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[titleLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:16],
[countLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16],
[countLabel.bottomAnchor constraintEqualToAnchor:card.bottomAnchor constant:-16],
]];
return card;
}
#pragma mark - Sync Button
- (void)setupSyncButton {
self.syncButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.syncButton.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
[self.syncButton setTitle:@"SYNC" forState:UIControlStateNormal];
[self.syncButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.syncButton.titleLabel.font = [UIFont boldSystemFontOfSize:16];
self.syncButton.layer.cornerRadius = 8;
self.syncButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.syncButton];
[NSLayoutConstraint activateConstraints:@[
[self.syncButton.topAnchor constraintEqualToAnchor:self.cardStack.bottomAnchor constant:16],
[self.syncButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[self.syncButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
[self.syncButton.heightAnchor constraintEqualToConstant:50],
[self.syncButton.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor constant:-16],
]];
}
@end
//QmsDashboardViewManager.mm
#import <React/RCTViewManager.h> #import <React/RCTViewManager.h>
#import <QmsPluginFramework/QmsPluginFramework.h> #import <QmsPluginFramework/QmsPluginFramework.h>
#import <QmsPluginFramework/QmsPlugin.h> #import <QmsPluginFramework/QmsPlugin.h>
......
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