Commit 3995f152 authored by Wei Han's avatar Wei Han

code update

parent 91919501
...@@ -8,32 +8,32 @@ ...@@ -8,32 +8,32 @@
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string> <string>ios-arm64</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
<dict> <dict>
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64</string> <string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
</array> </array>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#import "APIConfig.h" #import "APIConfig.h"
#import "ImageCacheHelper.h" #import "ImageCacheHelper.h"
@interface DashboardViewController () @interface DashboardViewController () <UIScrollViewDelegate>
@property (nonatomic, strong) NSArray *appointments; @property (nonatomic, strong) NSArray *appointments;
@property (nonatomic, strong) NSArray *issues; @property (nonatomic, strong) NSArray *issues;
...@@ -44,11 +44,14 @@ ...@@ -44,11 +44,14 @@
@property (nonatomic, strong) UIButton *backButton; @property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UIStackView *contentContainer; @property (nonatomic, strong) UIStackView *contentContainer;
@property (nonatomic, strong) UIView *inspectionBanner; @property (nonatomic, strong) UIView *inspectionBanner;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) UIView *stickyBar;
@end @end
@implementation DashboardViewController { @implementation DashboardViewController {
UIScrollView *_scrollView;
NSMutableDictionary *_sectionViews; NSMutableDictionary *_sectionViews;
CGFloat _currentY; CGFloat _currentY;
} }
...@@ -57,7 +60,8 @@ ...@@ -57,7 +60,8 @@
[super viewDidLoad]; [super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0]; self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
_sectionViews = [NSMutableDictionary dictionary]; _sectionViews = [NSMutableDictionary dictionary];
[self setupScrollView];
[self setupStickyBar];
[self setupHeader]; [self setupHeader];
[self setupScrollContent]; [self setupScrollContent];
[self setupFooter]; [self setupFooter];
...@@ -66,7 +70,7 @@ ...@@ -66,7 +70,7 @@
NSLog(@"dashboard.drawerController = %@", self.drawerController); NSLog(@"dashboard.drawerController = %@", self.drawerController);
// [[OfflineSyncManager shared] clearOfflineQueue]; //[[OfflineSyncManager shared] clearOfflineQueue];
} }
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
...@@ -125,35 +129,95 @@ ...@@ -125,35 +129,95 @@
} }
#pragma mark - Layout #pragma mark - Layout
- (void)viewDidLayoutSubviews { //- (void)viewDidLayoutSubviews {
NSLog(@"Header frame: %@", NSStringFromCGRect(_headerView.frame)); // NSLog(@"Header frame: %@", NSStringFromCGRect(_headerView.frame));
[super viewDidLayoutSubviews]; // [super viewDidLayoutSubviews];
UIView *footerView = self.view.subviews.lastObject; // UIView *footerView = self.view.subviews.lastObject;
CGFloat footerHeight = 80.0; // CGFloat footerHeight = 80.0;
CGFloat bottomInset = self.view.safeAreaInsets.bottom; // CGFloat bottomInset = self.view.safeAreaInsets.bottom;
footerView.frame = CGRectMake( // footerView.frame = CGRectMake(
0, // 0,
self.view.bounds.size.height - footerHeight - bottomInset, // self.view.bounds.size.height - footerHeight - bottomInset,
self.view.bounds.size.width, // self.view.bounds.size.width,
footerHeight + bottomInset // footerHeight + bottomInset
); // );
} //}
#pragma mark - Header #pragma mark - Header
- (void)setupStickyBar {
self.stickyBar = [[UIView alloc] init];
self.stickyBar.translatesAutoresizingMaskIntoConstraints = NO;
self.stickyBar.backgroundColor = [UIColor colorWithRed:0 green:0.43 blue:0.55 alpha:0]; // start fully transparent
[self.view addSubview:self.stickyBar];
[NSLayoutConstraint activateConstraints:@[
[self.stickyBar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.stickyBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.stickyBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.stickyBar.heightAnchor constraintEqualToConstant:44]
]];
// Back button
self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.backButton setImage:[UIImage systemImageNamed:@"chevron.backward"]
forState:UIControlStateNormal];
self.backButton.tintColor = UIColor.whiteColor;
[self.backButton addTarget:self action:@selector(onBack)
forControlEvents:UIControlEventTouchUpInside];
[self.stickyBar addSubview:self.backButton];
// Menu button
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];
[self.stickyBar addSubview:menuButton];
[NSLayoutConstraint activateConstraints:@[
[self.backButton.leadingAnchor constraintEqualToAnchor:self.stickyBar.leadingAnchor constant:8],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.stickyBar.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:24],
[self.backButton.heightAnchor constraintEqualToConstant:24],
[menuButton.trailingAnchor constraintEqualToAnchor:self.stickyBar.trailingAnchor constant:-16],
[menuButton.centerYAnchor constraintEqualToAnchor:self.stickyBar.centerYAnchor],
[menuButton.widthAnchor constraintEqualToConstant:26],
[menuButton.heightAnchor constraintEqualToConstant:26],
]];
UIView *statusBarBackground = [[UIView alloc] init];
statusBarBackground.translatesAutoresizingMaskIntoConstraints = NO;
statusBarBackground.backgroundColor =
[UIColor colorWithRed:0 green:0.43 blue:0.55 alpha:1.0];
[self.view insertSubview:statusBarBackground aboveSubview:self.scrollView];
[NSLayoutConstraint activateConstraints:@[
[statusBarBackground.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[statusBarBackground.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[statusBarBackground.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[statusBarBackground.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
]];
}
- (void)setupHeader { - (void)setupHeader {
CGFloat headerHeight = 220.0; CGFloat headerHeight = 255.0;
CGFloat maxImageHeight = 220.0; CGFloat maxImageHeight = 255.0;
// ---------- Header Container ---------- // ---------- Header Container ----------
self.headerView = [[UIView alloc] init]; self.headerView = [[UIView alloc] init];
self.headerView.translatesAutoresizingMaskIntoConstraints = NO; self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
self.headerView.backgroundColor = [UIColor colorWithRed:0 green:0.43 blue:0.55 alpha:1.0]; self.headerView.backgroundColor = [UIColor colorWithRed:0 green:0.43 blue:0.55 alpha:1.0];
[self.view addSubview:self.headerView]; [self.contentView addSubview:self.headerView];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.headerView.topAnchor constraintEqualToAnchor:self.view.topAnchor], [self.headerView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor],
[self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.headerView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
[self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.headerView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
[self.headerView.heightAnchor constraintEqualToConstant:headerHeight] [self.headerView.heightAnchor constraintEqualToConstant:headerHeight]
]]; ]];
...@@ -188,7 +252,7 @@ ...@@ -188,7 +252,7 @@
self.overlayImageView.translatesAutoresizingMaskIntoConstraints = NO; self.overlayImageView.translatesAutoresizingMaskIntoConstraints = NO;
self.overlayImageView.contentMode = UIViewContentModeScaleToFill; self.overlayImageView.contentMode = UIViewContentModeScaleToFill;
self.overlayImageView.userInteractionEnabled = NO; self.overlayImageView.userInteractionEnabled = NO;
self.overlayImageView.alpha = 0.5; // self.overlayImageView.alpha = 0.5;
[imageContainer addSubview:self.overlayImageView]; [imageContainer addSubview:self.overlayImageView];
...@@ -199,59 +263,17 @@ ...@@ -199,59 +263,17 @@
[self.overlayImageView.bottomAnchor constraintEqualToAnchor:imageContainer.bottomAnchor] [self.overlayImageView.bottomAnchor constraintEqualToAnchor:imageContainer.bottomAnchor]
]]; ]];
// ---------- Header Bar (Top) ----------
UIView *headerBar = [[UIView alloc] init];
headerBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.headerView addSubview:headerBar];
[NSLayoutConstraint activateConstraints:@[
[headerBar.topAnchor constraintEqualToAnchor:self.headerView.safeAreaLayoutGuide.topAnchor],
[headerBar.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor],
[headerBar.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor],
[headerBar.heightAnchor constraintEqualToConstant:44]
]];
// ---------- Project Name ---------- // ---------- Project Name ----------
self.projectNameLabel = [[UILabel alloc] init]; self.projectNameLabel = [[UILabel alloc] init];
self.projectNameLabel.translatesAutoresizingMaskIntoConstraints = NO; self.projectNameLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.projectNameLabel.font = [UIFont boldSystemFontOfSize:18]; self.projectNameLabel.font = [UIFont boldSystemFontOfSize:18];
self.projectNameLabel.textColor = UIColor.whiteColor; self.projectNameLabel.textColor = UIColor.whiteColor;
self.projectNameLabel.textAlignment = NSTextAlignmentCenter; self.projectNameLabel.textAlignment = NSTextAlignmentCenter;
[headerBar addSubview:self.projectNameLabel]; [imageContainer addSubview:self.projectNameLabel];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.projectNameLabel.centerXAnchor constraintEqualToAnchor:headerBar.centerXAnchor], [self.projectNameLabel.centerXAnchor constraintEqualToAnchor:self.stickyBar.centerXAnchor],
[self.projectNameLabel.centerYAnchor constraintEqualToAnchor:headerBar.centerYAnchor] [self.projectNameLabel.centerYAnchor constraintEqualToAnchor:self.stickyBar.centerYAnchor]
]];
// ---------- Menu Button ----------
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]
]];
// ---------- Back Button ----------
self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.backButton setImage:[UIImage systemImageNamed:@"chevron.backward"] forState:UIControlStateNormal];
self.backButton.tintColor = UIColor.whiteColor;
[self.backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
[headerBar addSubview:self.backButton];
[NSLayoutConstraint activateConstraints:@[
[self.backButton.leadingAnchor constraintEqualToAnchor:headerBar.leadingAnchor constant:8],
[self.backButton.centerYAnchor constraintEqualToAnchor:headerBar.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:24],
[self.backButton.heightAnchor constraintEqualToConstant:24]
]]; ]];
// ---------- Unit Name ---------- // ---------- Unit Name ----------
...@@ -281,6 +303,21 @@ ...@@ -281,6 +303,21 @@
[self.infoButton.heightAnchor constraintEqualToConstant:24] [self.infoButton.heightAnchor constraintEqualToConstant:24]
]]; ]];
// ---------- Dark Overlay ----------
UIView *darkOverlay = [[UIView alloc] init];
darkOverlay.translatesAutoresizingMaskIntoConstraints = NO;
darkOverlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.35];
darkOverlay.userInteractionEnabled = NO;
[imageContainer addSubview:darkOverlay];
[NSLayoutConstraint activateConstraints:@[
[darkOverlay.topAnchor constraintEqualToAnchor:imageContainer.topAnchor],
[darkOverlay.leadingAnchor constraintEqualToAnchor:imageContainer.leadingAnchor],
[darkOverlay.trailingAnchor constraintEqualToAnchor:imageContainer.trailingAnchor],
[darkOverlay.bottomAnchor constraintEqualToAnchor:imageContainer.bottomAnchor]
]];
// ---------- Load Remote Image & Overlay ---------- // ---------- Load Remote Image & Overlay ----------
NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSBundle *bundle = [NSBundle bundleForClass:[self class]];
UIImage *overlayImage = UIImage *overlayImage =
...@@ -297,7 +334,10 @@ ...@@ -297,7 +334,10 @@
NSURL *url = [NSURL URLWithString:remoteHeaderURL]; NSURL *url = [NSURL URLWithString:remoteHeaderURL];
[ImageCacheHelper loadImageWithURL:url completion:^(UIImage *image) { [ImageCacheHelper loadImageWithURL:url completion:^(UIImage *image) {
self.backgroundImageView.image = image ?: [UIImage imageNamed:@"header_bg"]; self.backgroundImageView.image = image ?: [UIImage imageNamed:@"header_bg"];
[imageContainer bringSubviewToFront:self.backgroundImageView];
[imageContainer bringSubviewToFront:darkOverlay];
[imageContainer bringSubviewToFront:self.overlayImageView]; [imageContainer bringSubviewToFront:self.overlayImageView];
[imageContainer bringSubviewToFront:self.projectNameLabel];
}]; }];
} else { } else {
self.backgroundImageView.image = [UIImage imageNamed:@"header_bg"]; self.backgroundImageView.image = [UIImage imageNamed:@"header_bg"];
...@@ -307,7 +347,7 @@ ...@@ -307,7 +347,7 @@
#pragma mark - Footer #pragma mark - Footer
- (void)setupFooter { - (void)setupFooter {
CGFloat footerHeight = 80.0; CGFloat footerHeight = 72.0;
CGFloat bottomInset = self.view.safeAreaInsets.bottom; CGFloat bottomInset = self.view.safeAreaInsets.bottom;
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake( UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(
0, 0,
...@@ -320,9 +360,13 @@ ...@@ -320,9 +360,13 @@
footerView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; footerView.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor;
footerView.layer.shadowOpacity = 0.8; footerView.layer.shadowOpacity = 0.8;
footerView.layer.shadowOffset = CGSizeMake(0, -1); footerView.layer.shadowOffset = CGSizeMake(0, -1);
footerView.backgroundColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0];
footerView.layer.cornerRadius = 16.0;
footerView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner; // top-left & top-right
footerView.clipsToBounds = YES;
[self.view addSubview:footerView]; [self.view addSubview:footerView];
NSArray *titles = @[ @"Make Appointment", @"Add Issue", @"View Access Item" ]; NSArray *titles = @[ @"Make Appt.", @"Add Issue", @"Access Item" ];
NSArray *icons = @[ @"calendar", @"plus.circle", @"list.bullet" ]; NSArray *icons = @[ @"calendar", @"plus.circle", @"list.bullet" ];
CGFloat buttonWidth = self.view.bounds.size.width / titles.count; CGFloat buttonWidth = self.view.bounds.size.width / titles.count;
...@@ -330,9 +374,9 @@ ...@@ -330,9 +374,9 @@
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(i * buttonWidth, 0, buttonWidth, footerHeight); button.frame = CGRectMake(i * buttonWidth, 0, buttonWidth, footerHeight);
[button setTitle:titles[i] forState:UIControlStateNormal]; [button setTitle:titles[i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0] forState:UIControlStateNormal]; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont boldSystemFontOfSize:13]; button.titleLabel.font = [UIFont boldSystemFontOfSize:13];
button.tintColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0]; button.tintColor = [UIColor whiteColor];
[button setImage:[UIImage systemImageNamed:icons[i]] forState:UIControlStateNormal]; [button setImage:[UIImage systemImageNamed:icons[i]] forState:UIControlStateNormal];
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
...@@ -391,73 +435,64 @@ ...@@ -391,73 +435,64 @@
} }
#pragma mark - Scroll Content #pragma mark - Scroll Content
- (void)setupScrollContent { - (void)setupScrollView {
// ScrollView self.scrollView = [[UIScrollView alloc] init];
_scrollView = [[UIScrollView alloc] init]; self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
_scrollView.translatesAutoresizingMaskIntoConstraints = NO; self.scrollView.alwaysBounceVertical = YES;
_scrollView.alwaysBounceVertical = YES; self.scrollView.delegate = self;
[self.view addSubview:_scrollView]; [self.view addSubview:self.scrollView];
CGFloat footerHeight = 80.0; self.contentView = [[UIView alloc] init];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:self.contentView];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[_scrollView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor], [self.scrollView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[_scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[_scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[_scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-footerHeight] [self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[self.contentView.topAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.topAnchor],
[self.contentView.leadingAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.leadingAnchor],
[self.contentView.trailingAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.trailingAnchor],
[self.contentView.bottomAnchor constraintEqualToAnchor:self.scrollView.contentLayoutGuide.bottomAnchor],
[self.contentView.widthAnchor constraintEqualToAnchor:self.scrollView.frameLayoutGuide.widthAnchor],
]]; ]];
}
- (void)setupScrollContent {
UIView *banner = [self buildInspectionChecklistBanner]; UIView *banner = [self buildInspectionChecklistBanner];
UIView *stackContainer = [[UIView alloc] init];
stackContainer.translatesAutoresizingMaskIntoConstraints = NO;
[_scrollView addSubview:stackContainer];
CGFloat topOffset = 16; CGFloat topOffset = 16;
if (banner) { if (banner) {
banner.translatesAutoresizingMaskIntoConstraints = NO; banner.translatesAutoresizingMaskIntoConstraints = NO;
[_scrollView addSubview:banner]; [self.contentView addSubview:banner];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[banner.topAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.topAnchor constant:topOffset], [banner.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:topOffset],
[banner.leadingAnchor constraintEqualToAnchor:_scrollView.leadingAnchor constant:16], [banner.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[banner.trailingAnchor constraintEqualToAnchor:_scrollView.trailingAnchor constant:-16], [banner.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[banner.heightAnchor constraintEqualToConstant:90] [banner.heightAnchor constraintEqualToConstant:90]
]]; ]];
topOffset += 90 + 16; // stack starts after banner + spacing topOffset += 90 + 16;
} }
// Content container (STACK VIEW)
UIStackView *stack = [[UIStackView alloc] init]; UIStackView *stack = [[UIStackView alloc] init];
stack.axis = UILayoutConstraintAxisVertical; stack.axis = UILayoutConstraintAxisVertical;
stack.spacing = 16; stack.spacing = 22;
stack.translatesAutoresizingMaskIntoConstraints = NO; stack.translatesAutoresizingMaskIntoConstraints = NO;
stack.layoutMargins = UIEdgeInsetsMake(0, 16, 16, 16); stack.layoutMargins = UIEdgeInsetsMake(0, 16, 16, 16);
stack.layoutMarginsRelativeArrangement = YES; stack.layoutMarginsRelativeArrangement = YES;
[stackContainer addSubview:stack]; [self.contentView addSubview:stack];
self.contentContainer = stack; self.contentContainer = stack;
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[stack.topAnchor constraintEqualToAnchor:stackContainer.topAnchor], [stack.topAnchor constraintEqualToAnchor:(banner ? banner.bottomAnchor : self.headerView.bottomAnchor)
[stack.leadingAnchor constraintEqualToAnchor:stackContainer.leadingAnchor], constant:16],
[stack.trailingAnchor constraintEqualToAnchor:stackContainer.trailingAnchor], [stack.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
[stack.bottomAnchor constraintEqualToAnchor:stackContainer.bottomAnchor], [stack.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
[stack.widthAnchor constraintEqualToAnchor:stackContainer.widthAnchor] [stack.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor]
]];
[NSLayoutConstraint activateConstraints:@[
// Top/bottom for vertical scrolling
[stackContainer.topAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.topAnchor constant:topOffset],
[stackContainer.bottomAnchor constraintEqualToAnchor:_scrollView.contentLayoutGuide.bottomAnchor],
// ⚡ Width locked to frame to prevent horizontal scroll
[stackContainer.widthAnchor constraintEqualToAnchor:_scrollView.frameLayoutGuide.widthAnchor],
// Leading/trailing optional, can just pin to zero if width is fixed
[stackContainer.leadingAnchor constraintEqualToAnchor:_scrollView.leadingAnchor],
[stackContainer.trailingAnchor constraintEqualToAnchor:_scrollView.trailingAnchor]
]]; ]];
} }
...@@ -556,7 +591,7 @@ ...@@ -556,7 +591,7 @@
if (pill) { if (pill) {
[constraints addObjectsFromArray:@[ [constraints addObjectsFromArray:@[
[pill.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor constant:8], [pill.topAnchor constraintEqualToAnchor:titleLabel.bottomAnchor constant:14],
[pill.leadingAnchor constraintEqualToAnchor:banner.leadingAnchor constant:16], [pill.leadingAnchor constraintEqualToAnchor:banner.leadingAnchor constant:16],
[pill.heightAnchor constraintEqualToConstant:28], [pill.heightAnchor constraintEqualToConstant:28],
[pill.bottomAnchor constraintEqualToAnchor:banner.bottomAnchor constant:-16] [pill.bottomAnchor constraintEqualToAnchor:banner.bottomAnchor constant:-16]
...@@ -793,7 +828,7 @@ ...@@ -793,7 +828,7 @@
[hScroll.topAnchor constraintEqualToAnchor:title.bottomAnchor constant:12], [hScroll.topAnchor constraintEqualToAnchor:title.bottomAnchor constant:12],
[hScroll.leadingAnchor constraintEqualToAnchor:section.leadingAnchor], [hScroll.leadingAnchor constraintEqualToAnchor:section.leadingAnchor],
[hScroll.trailingAnchor constraintEqualToAnchor:section.trailingAnchor], [hScroll.trailingAnchor constraintEqualToAnchor:section.trailingAnchor],
[hScroll.heightAnchor constraintEqualToConstant:90], [hScroll.heightAnchor constraintEqualToConstant:80],
[hScroll.bottomAnchor constraintEqualToAnchor:section.bottomAnchor] // important [hScroll.bottomAnchor constraintEqualToAnchor:section.bottomAnchor] // important
]]; ]];
...@@ -942,7 +977,7 @@ ...@@ -942,7 +977,7 @@
[section addSubview:list]; [section addSubview:list];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[list.topAnchor constraintEqualToAnchor:title.bottomAnchor], [list.topAnchor constraintEqualToAnchor:title.bottomAnchor constant:12],
[list.leadingAnchor constraintEqualToAnchor:section.leadingAnchor], [list.leadingAnchor constraintEqualToAnchor:section.leadingAnchor],
[list.trailingAnchor constraintEqualToAnchor:section.trailingAnchor], [list.trailingAnchor constraintEqualToAnchor:section.trailingAnchor],
[list.bottomAnchor constraintEqualToAnchor:section.bottomAnchor] [list.bottomAnchor constraintEqualToAnchor:section.bottomAnchor]
...@@ -967,7 +1002,7 @@ ...@@ -967,7 +1002,7 @@
card.layer.shadowOpacity = 0.3; card.layer.shadowOpacity = 0.3;
card.layer.shadowOffset = CGSizeMake(0, 1); card.layer.shadowOffset = CGSizeMake(0, 1);
[card.heightAnchor constraintEqualToConstant:90].active = YES; [card.heightAnchor constraintEqualToConstant:92].active = YES;
NSString *appointmentType = item[@"appointment_type"] ?: @"-"; NSString *appointmentType = item[@"appointment_type"] ?: @"-";
NSString *status = item[@"status"] ?: @"-"; NSString *status = item[@"status"] ?: @"-";
...@@ -1015,8 +1050,8 @@ ...@@ -1015,8 +1050,8 @@
[card addSubview:desc]; [card addSubview:desc];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[iconCircle.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12], [iconCircle.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[iconCircle.topAnchor constraintEqualToAnchor:card.topAnchor constant:14], [iconCircle.topAnchor constraintEqualToAnchor:card.topAnchor constant:12],
[iconCircle.widthAnchor constraintEqualToConstant:24], [iconCircle.widthAnchor constraintEqualToConstant:24],
[iconCircle.heightAnchor constraintEqualToConstant:24], [iconCircle.heightAnchor constraintEqualToConstant:24],
...@@ -1026,15 +1061,15 @@ ...@@ -1026,15 +1061,15 @@
[bell.heightAnchor constraintEqualToConstant:16], [bell.heightAnchor constraintEqualToConstant:16],
[statusLabel.leadingAnchor constraintEqualToAnchor:iconCircle.trailingAnchor constant:8], [statusLabel.leadingAnchor constraintEqualToAnchor:iconCircle.trailingAnchor constant:8],
[statusLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:12], [statusLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:14],
[timeLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12], [timeLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12],
[timeLabel.centerYAnchor constraintEqualToAnchor:statusLabel.centerYAnchor], [timeLabel.centerYAnchor constraintEqualToAnchor:statusLabel.centerYAnchor],
[desc.topAnchor constraintEqualToAnchor:statusLabel.bottomAnchor constant:6], [desc.topAnchor constraintEqualToAnchor:card.topAnchor constant:41],
[desc.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16], [desc.leadingAnchor constraintEqualToAnchor:statusLabel.leadingAnchor],
[desc.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-16], [desc.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-20],
[desc.bottomAnchor constraintLessThanOrEqualToAnchor:card.bottomAnchor constant:-8] [desc.bottomAnchor constraintLessThanOrEqualToAnchor:card.bottomAnchor constant:-15]
]]; ]];
objc_setAssociatedObject(card, "appointmentData", item, OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(card, "appointmentData", item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
...@@ -1107,7 +1142,7 @@ ...@@ -1107,7 +1142,7 @@
[section addSubview:list]; [section addSubview:list];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[list.topAnchor constraintEqualToAnchor:title.bottomAnchor], [list.topAnchor constraintEqualToAnchor:title.bottomAnchor constant:12],
[list.leadingAnchor constraintEqualToAnchor:section.leadingAnchor], [list.leadingAnchor constraintEqualToAnchor:section.leadingAnchor],
[list.trailingAnchor constraintEqualToAnchor:section.trailingAnchor], [list.trailingAnchor constraintEqualToAnchor:section.trailingAnchor],
[list.bottomAnchor constraintEqualToAnchor:section.bottomAnchor] [list.bottomAnchor constraintEqualToAnchor:section.bottomAnchor]
...@@ -1130,7 +1165,7 @@ ...@@ -1130,7 +1165,7 @@
card.layer.shadowOpacity = 0.3; card.layer.shadowOpacity = 0.3;
card.layer.shadowOffset = CGSizeMake(0, 1); card.layer.shadowOffset = CGSizeMake(0, 1);
[card.heightAnchor constraintGreaterThanOrEqualToConstant:110].active = YES; [card.heightAnchor constraintGreaterThanOrEqualToConstant:92].active = YES;
NSString *status = item[@"status_external"] ?: @"Unknown"; NSString *status = item[@"status_external"] ?: @"Unknown";
NSString *formattedDate = [self formatDate:item[@"created_at"]]; NSString *formattedDate = [self formatDate:item[@"created_at"]];
...@@ -1157,7 +1192,7 @@ ...@@ -1157,7 +1192,7 @@
dateLabel.textAlignment = NSTextAlignmentRight; dateLabel.textAlignment = NSTextAlignmentRight;
[card addSubview:dateLabel]; [card addSubview:dateLabel];
CGFloat imageSize = 44; CGFloat imageSize = 30;
UIImageView *thumb = [[UIImageView alloc] init]; UIImageView *thumb = [[UIImageView alloc] init];
thumb.translatesAutoresizingMaskIntoConstraints = NO; thumb.translatesAutoresizingMaskIntoConstraints = NO;
thumb.layer.cornerRadius = 6; thumb.layer.cornerRadius = 6;
...@@ -1195,12 +1230,12 @@ ...@@ -1195,12 +1230,12 @@
[card addSubview:info]; [card addSubview:info];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[dot.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12], [dot.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[dot.topAnchor constraintEqualToAnchor:card.topAnchor constant:12], [dot.topAnchor constraintEqualToAnchor:card.topAnchor constant:12],
[dot.widthAnchor constraintEqualToConstant:16], [dot.widthAnchor constraintEqualToConstant:16],
[dot.heightAnchor constraintEqualToConstant:16], [dot.heightAnchor constraintEqualToConstant:16],
[statusLabel.leadingAnchor constraintEqualToAnchor:dot.trailingAnchor constant:6], [statusLabel.leadingAnchor constraintEqualToAnchor:dot.trailingAnchor constant:14],
[statusLabel.centerYAnchor constraintEqualToAnchor:dot.centerYAnchor], [statusLabel.centerYAnchor constraintEqualToAnchor:dot.centerYAnchor],
[dateLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12], [dateLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12],
...@@ -1211,9 +1246,9 @@ ...@@ -1211,9 +1246,9 @@
[thumb.widthAnchor constraintEqualToConstant:imageSize], [thumb.widthAnchor constraintEqualToConstant:imageSize],
[thumb.heightAnchor constraintEqualToConstant:imageSize], [thumb.heightAnchor constraintEqualToConstant:imageSize],
[info.leadingAnchor constraintEqualToAnchor:thumb.trailingAnchor constant:10], [info.leadingAnchor constraintEqualToAnchor:thumb.trailingAnchor constant:14],
[info.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12], [info.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-14],
[info.centerYAnchor constraintEqualToAnchor:thumb.centerYAnchor], [info.topAnchor constraintEqualToAnchor:card.topAnchor constant:41],
[info.bottomAnchor constraintLessThanOrEqualToAnchor:card.bottomAnchor constant:-10] [info.bottomAnchor constraintLessThanOrEqualToAnchor:card.bottomAnchor constant:-10]
]]; ]];
...@@ -1493,4 +1528,21 @@ ...@@ -1493,4 +1528,21 @@
[self.navigationController popViewControllerAnimated:YES]; [self.navigationController popViewControllerAnimated:YES];
} }
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat offsetY = scrollView.contentOffset.y;
// Parallax effect for the header image
if (offsetY < 0) {
self.backgroundImageView.transform = CGAffineTransformMakeTranslation(0, offsetY / 2);
} else {
self.backgroundImageView.transform = CGAffineTransformIdentity;
}
// Gradually fade in sticky bar
CGFloat fadeStart = 0;
CGFloat fadeEnd = 100; // how far scroll before fully opaque
CGFloat alpha = MIN(MAX((offsetY - fadeStart) / (fadeEnd - fadeStart), 0), 1);
self.stickyBar.backgroundColor = [UIColor colorWithRed:0 green:0.43 blue:0.55 alpha:alpha];
}
@end @end
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
@property (nonatomic) NSLayoutConstraint *infoBottom; @property (nonatomic) NSLayoutConstraint *infoBottom;
@property (nonatomic) NSLayoutConstraint *documentsBottom; @property (nonatomic) NSLayoutConstraint *documentsBottom;
@property (nonatomic) NSLayoutConstraint *formsBottom; @property (nonatomic) NSLayoutConstraint *formsBottom;
@property (nonatomic, strong) UILabel *jointTitleLabel;
// Sections for tabs // Sections for tabs
@property (nonatomic, strong) UIView *infoContainer; @property (nonatomic, strong) UIView *infoContainer;
...@@ -238,12 +239,12 @@ typedef struct { ...@@ -238,12 +239,12 @@ typedef struct {
[self.infoContainer addSubview:self.ownerStack]; [self.infoContainer addSubview:self.ownerStack];
// --- Joint Owners Title --- // --- Joint Owners Title ---
UILabel *jointTitle = [[UILabel alloc] init]; self.jointTitleLabel = [[UILabel alloc] init];
jointTitle.text = @"Joint Owner Details"; self.jointTitleLabel.text = @"Joint Owner Details";
jointTitle.font = [UIFont boldSystemFontOfSize:16]; self.jointTitleLabel.font = [UIFont boldSystemFontOfSize:16];
jointTitle.textColor = UIColor.darkGrayColor; self.jointTitleLabel.textColor = UIColor.darkGrayColor;
jointTitle.translatesAutoresizingMaskIntoConstraints = NO; self.jointTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.infoContainer addSubview:jointTitle]; [self.infoContainer addSubview:self.jointTitleLabel];
// --- Joint Owners Stack --- // --- Joint Owners Stack ---
self.jointOwnersStack = [[UIStackView alloc] init]; self.jointOwnersStack = [[UIStackView alloc] init];
...@@ -276,10 +277,10 @@ typedef struct { ...@@ -276,10 +277,10 @@ typedef struct {
[self.ownerStack.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16], [self.ownerStack.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16],
[self.ownerStack.trailingAnchor constraintEqualToAnchor:self.infoContainer.trailingAnchor constant:-16], [self.ownerStack.trailingAnchor constraintEqualToAnchor:self.infoContainer.trailingAnchor constant:-16],
[jointTitle.topAnchor constraintEqualToAnchor:self.ownerStack.bottomAnchor constant:20], [self.jointTitleLabel.topAnchor constraintEqualToAnchor:self.ownerStack.bottomAnchor constant:20],
[jointTitle.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16], [self.jointTitleLabel.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16],
[self.jointOwnersStack.topAnchor constraintEqualToAnchor:jointTitle.bottomAnchor constant:12], [self.jointOwnersStack.topAnchor constraintEqualToAnchor:self.jointTitleLabel.bottomAnchor constant:12],
[self.jointOwnersStack.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16], [self.jointOwnersStack.leadingAnchor constraintEqualToAnchor:self.infoContainer.leadingAnchor constant:16],
[self.jointOwnersStack.trailingAnchor constraintEqualToAnchor:self.infoContainer.trailingAnchor constant:-16], [self.jointOwnersStack.trailingAnchor constraintEqualToAnchor:self.infoContainer.trailingAnchor constant:-16],
...@@ -643,7 +644,6 @@ typedef struct { ...@@ -643,7 +644,6 @@ typedef struct {
} }
maxTitleWidth += 6; maxTitleWidth += 6;
UIStackView* (^OwnerCard)(NSDictionary *) = ^UIStackView* (NSDictionary *owner) { UIStackView* (^OwnerCard)(NSDictionary *) = ^UIStackView* (NSDictionary *owner) {
UIStackView *card = [[UIStackView alloc] init]; UIStackView *card = [[UIStackView alloc] init];
...@@ -699,6 +699,11 @@ typedef struct { ...@@ -699,6 +699,11 @@ typedef struct {
[self.jointOwnersStack addArrangedSubview:OwnerCard(owner)]; [self.jointOwnersStack addArrangedSubview:OwnerCard(owner)];
} }
BOOL hasJointOwners = self.jointOwnersStack.arrangedSubviews.count > 0;
self.jointOwnersStack.hidden = !hasJointOwners;
self.jointTitleLabel.hidden = !hasJointOwners;
// ------------------------ // ------------------------
// 2️⃣ UNIT INFO SECTION // 2️⃣ UNIT INFO SECTION
// ------------------------ // ------------------------
......
...@@ -34,10 +34,10 @@ ...@@ -34,10 +34,10 @@
// label // label
self.nameLabel = [[UILabel alloc] init]; self.nameLabel = [[UILabel alloc] init];
self.nameLabel.font = [UIFont boldSystemFontOfSize:20]; self.nameLabel.font = [UIFont boldSystemFontOfSize:18];
self.nameLabel.textColor = UIColor.whiteColor; self.nameLabel.textColor = UIColor.whiteColor;
self.nameLabel.backgroundColor = // self.nameLabel.backgroundColor =
[[UIColor blackColor] colorWithAlphaComponent:0.35]; // [[UIColor blackColor] colorWithAlphaComponent:0.35];
self.nameLabel.numberOfLines = 2; self.nameLabel.numberOfLines = 2;
self.nameLabel.translatesAutoresizingMaskIntoConstraints = NO; self.nameLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.nameLabel]; [self.contentView addSubview:self.nameLabel];
...@@ -116,24 +116,24 @@ ...@@ -116,24 +116,24 @@
NSLog(@"ClientCode: %@", self.ClientCode); NSLog(@"ClientCode: %@", self.ClientCode);
NSLog(@"user_token: %@", self.user_token); NSLog(@"user_token: %@", self.user_token);
[self showLoadingOverlay:@"Loading..."]; // [self showLoadingOverlay:@"Loading..."];
//
if (![self isReadyToLoadDashboard]) { // if (![self isReadyToLoadDashboard]) {
NSLog(@"⏳ Waiting for all credentials to be ready..."); // NSLog(@"⏳ Waiting for all credentials to be ready...");
return; // return;
} // }
//
if (_isLoadingDashboard) return; // if (_isLoadingDashboard) return;
//
self.isLoadingDashboard = YES; // self.isLoadingDashboard = YES;
//
NSLog(@"✅ All credentials ready. ClientID: %@, ClientCode: %@, user_token: %@", // NSLog(@"✅ All credentials ready. ClientID: %@, ClientCode: %@, user_token: %@",
self.ClientID, self.ClientCode, self.user_token); // self.ClientID, self.ClientCode, self.user_token);
//
//
[APIConfig setAuthTokem:self.user_token]; // [APIConfig setAuthTokem:self.user_token];
[APIConfig setClientId:self.ClientID]; // [APIConfig setClientId:self.ClientID];
[self requestProjectList]; self.ClientCode = @"spt";
[self requestCompanyCode]; [self requestCompanyCode];
} }
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
- (void)setupCollectionView { - (void)setupCollectionView {
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical; layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.minimumLineSpacing = 16; layout.minimumLineSpacing = 12;
layout.minimumInteritemSpacing = 16; layout.minimumInteritemSpacing = 16;
layout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16); layout.sectionInset = UIEdgeInsetsMake(16, 16, 16, 16);
...@@ -202,7 +202,7 @@ ...@@ -202,7 +202,7 @@
// constraints // constraints
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.collectionView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:8], [self.collectionView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:20],
[self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.collectionView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.collectionView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] [self.collectionView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
...@@ -273,7 +273,7 @@ ...@@ -273,7 +273,7 @@
CGFloat horizontalInset = 16 * 2; // section inset left + right CGFloat horizontalInset = 16 * 2; // section inset left + right
CGFloat width = collectionView.bounds.size.width - horizontalInset; CGFloat width = collectionView.bounds.size.width - horizontalInset;
CGFloat height = 200; // OG-style banner height CGFloat height = 140; // OG-style banner height
return CGSizeMake(width, height); return CGSizeMake(width, height);
} }
...@@ -400,16 +400,12 @@ ...@@ -400,16 +400,12 @@
return; return;
} }
NSArray *project = data[@"Data"];
if (![project isKindOfClass:[NSArray class]]) {
NSLog(@"❌ Invalid project list format");
return;
}
if (!error) { if (!error) {
NSString *rawURL = data[@"Data"][@"url_path"]; NSString *rawURL = data[@"Data"][@"url_path"];
NSString *baseURL = rawURL; NSString *baseURL = rawURL;
NSLog(@"base url: %@", baseURL);
// remove trailing slash if exists // remove trailing slash if exists
if ([baseURL hasSuffix:@"/"]) { if ([baseURL hasSuffix:@"/"]) {
baseURL = [baseURL substringToIndex:baseURL.length - 1]; baseURL = [baseURL substringToIndex:baseURL.length - 1];
...@@ -418,7 +414,8 @@ ...@@ -418,7 +414,8 @@
// append /api // append /api
baseURL = [baseURL stringByAppendingString:@"/api"]; baseURL = [baseURL stringByAppendingString:@"/api"];
NSLog(@"baseURL: %@", baseURL); NSLog(@"baseURL: %@", baseURL);
// [APIConfig setBaseURL:baseURL]; [APIConfig setBaseURL:baseURL];
[self requestProjectList];
} }
}]; }];
} }
......
...@@ -110,10 +110,10 @@ ...@@ -110,10 +110,10 @@
[self.view addSubview:self.searchBar]; [self.view addSubview:self.searchBar];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.searchBar.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:8], [self.searchBar.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor constant:0],
[self.searchBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16], [self.searchBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[self.searchBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16], [self.searchBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
[self.searchBar.heightAnchor constraintEqualToConstant:44] [self.searchBar.heightAnchor constraintEqualToConstant:72]
]]; ]];
} }
...@@ -151,11 +151,19 @@ ...@@ -151,11 +151,19 @@
[self.view addSubview:self.tableView]; [self.view addSubview:self.tableView];
UILabel *footerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 50)];
footerLabel.text = @"All items displayed";
footerLabel.textColor = UIColor.systemGrayColor;
footerLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
footerLabel.textAlignment = NSTextAlignmentCenter;
self.tableView.tableFooterView = footerLabel;
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[self.tableView.topAnchor constraintEqualToAnchor:self.searchBar.bottomAnchor constant:8], [self.tableView.topAnchor constraintEqualToAnchor:self.searchBar.bottomAnchor constant:12],
[self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], [self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
[self.tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor] [self.tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:self.view.safeAreaInsets.bottom]
]]; ]];
} }
...@@ -169,6 +177,7 @@ ...@@ -169,6 +177,7 @@
UITableViewCell *cell = UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"UnitCell" [tableView dequeueReusableCellWithIdentifier:@"UnitCell"
forIndexPath:indexPath]; forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// ---- Reset reused cell ---- // ---- Reset reused cell ----
for (UIView *subview in cell.contentView.subviews) { for (UIView *subview in cell.contentView.subviews) {
...@@ -186,25 +195,30 @@ ...@@ -186,25 +195,30 @@
// ---- Arrow ---- // ---- Arrow ----
UIImageView *arrow = [[UIImageView alloc] initWithImage: UIImageView *arrow = [[UIImageView alloc] initWithImage:
[UIImage systemImageNamed:@"chevron.right"]]; [UIImage systemImageNamed:@"chevron.right"]];
arrow.tintColor = UIColor.systemGrayColor; arrow.tintColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
arrow.translatesAutoresizingMaskIntoConstraints = NO; arrow.translatesAutoresizingMaskIntoConstraints = NO;
// ---- Card styling ---- // ---- Card styling ----
cell.backgroundColor = UIColor.clearColor; UIView *cardView = [[UIView alloc] init];
cell.selectionStyle = UITableViewCellSelectionStyleNone; cardView.backgroundColor = UIColor.whiteColor;
cardView.layer.cornerRadius = 12;
cell.contentView.backgroundColor = UIColor.whiteColor; cardView.layer.borderWidth = 1;
cell.contentView.layer.cornerRadius = 12; cardView.layer.borderColor = UIColor.systemGray4Color.CGColor;
cell.contentView.layer.borderWidth = 1; cardView.translatesAutoresizingMaskIntoConstraints = NO;
cell.contentView.layer.borderColor = UIColor.systemGray4Color.CGColor; [cell.contentView addSubview:cardView];
cell.contentView.clipsToBounds = YES;
// Put label & arrow inside cardView
// ---- Add views ---- [cardView addSubview:label];
[cell.contentView addSubview:label]; [cardView addSubview:arrow];
[cell.contentView addSubview:arrow];
// ---- Constraints ---- // ---- Constraints ----
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
// Cardview
[cardView.topAnchor constraintEqualToAnchor:cell.contentView.topAnchor constant:8], // vertical spacing top
[cardView.bottomAnchor constraintEqualToAnchor:cell.contentView.bottomAnchor constant:-8], // vertical spacing bottom
[cardView.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:0], // horizontal spacing
[cardView.trailingAnchor constraintEqualToAnchor:cell.contentView.trailingAnchor constant:0],
// Label // Label
[label.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:16], [label.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:16],
[label.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor], [label.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor],
...@@ -230,7 +244,7 @@ forRowAtIndexPath:(NSIndexPath *)indexPath { ...@@ -230,7 +244,7 @@ forRowAtIndexPath:(NSIndexPath *)indexPath {
- (CGFloat)tableView:(UITableView *)tableView - (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath { heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 64; return 66;
} }
- (void)tableView:(UITableView *)tableView - (void)tableView:(UITableView *)tableView
......
...@@ -60,8 +60,7 @@ ...@@ -60,8 +60,7 @@
#pragma mark - Header #pragma mark - Header
- (void)setupHeader { - (void)setupHeader {
CGFloat statusBarHeight = UIApplication.sharedApplication.statusBarFrame.size.height; self.headerView = [[UIView alloc] init];
self.headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, statusBarHeight + 60)];
self.headerView.backgroundColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0]; self.headerView.backgroundColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0];
self.headerView.translatesAutoresizingMaskIntoConstraints = NO; self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.headerView]; [self.view addSubview:self.headerView];
......
...@@ -82,30 +82,31 @@ ...@@ -82,30 +82,31 @@
[card.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:6], [card.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:6],
[card.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:10], [card.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:10],
[card.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-10], [card.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-10],
[card.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-6], [card.heightAnchor constraintEqualToConstant:141],
[self.thumbView.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12],
[self.thumbView.topAnchor constraintEqualToAnchor:card.topAnchor constant:12],
[self.thumbView.widthAnchor constraintEqualToConstant:44],
[self.thumbView.heightAnchor constraintEqualToConstant:44],
[self.statusLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12], [self.statusLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12],
[self.statusLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:12], [self.statusLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:12],
[self.statusLabel.widthAnchor constraintEqualToConstant:70], [self.statusLabel.widthAnchor constraintEqualToConstant:70],
[self.statusLabel.heightAnchor constraintEqualToConstant:24], [self.statusLabel.heightAnchor constraintEqualToConstant:24],
[self.referenceLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[self.referenceLabel.trailingAnchor constraintEqualToAnchor:self.statusLabel.leadingAnchor constant:16],
[self.referenceLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:16],
[self.thumbView.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:16],
[self.thumbView.topAnchor constraintEqualToAnchor:self.referenceLabel.bottomAnchor constant:12],
[self.thumbView.widthAnchor constraintEqualToConstant:44],
[self.thumbView.heightAnchor constraintEqualToConstant:44],
[self.locationLabel.leadingAnchor constraintEqualToAnchor:self.thumbView.trailingAnchor constant:12], [self.locationLabel.leadingAnchor constraintEqualToAnchor:self.thumbView.trailingAnchor constant:12],
[self.locationLabel.topAnchor constraintEqualToAnchor:card.topAnchor constant:12], [self.locationLabel.bottomAnchor constraintEqualToAnchor:self.thumbView.centerYAnchor constant:-1],
[self.createdLabel.leadingAnchor constraintEqualToAnchor:self.thumbView.trailingAnchor constant:12], [self.createdLabel.leadingAnchor constraintEqualToAnchor:self.thumbView.trailingAnchor constant:12],
[self.createdLabel.topAnchor constraintEqualToAnchor:self.locationLabel.bottomAnchor constant:4], [self.createdLabel.topAnchor constraintEqualToAnchor:self.thumbView.centerYAnchor constant:1],
[self.referenceLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12],
[self.referenceLabel.topAnchor constraintEqualToAnchor:self.thumbView.bottomAnchor constant:8],
[self.detailsLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12], [self.detailsLabel.leadingAnchor constraintEqualToAnchor:card.leadingAnchor constant:12],
[self.detailsLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12], [self.detailsLabel.trailingAnchor constraintEqualToAnchor:card.trailingAnchor constant:-12],
[self.detailsLabel.topAnchor constraintEqualToAnchor:self.referenceLabel.bottomAnchor constant:4], [self.detailsLabel.topAnchor constraintEqualToAnchor:self.thumbView.bottomAnchor constant:12],
[self.detailsLabel.bottomAnchor constraintEqualToAnchor:card.bottomAnchor constant:-12], [self.detailsLabel.bottomAnchor constraintEqualToAnchor:card.bottomAnchor constant:-12],
]]; ]];
} }
......
...@@ -715,8 +715,6 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath { ...@@ -715,8 +715,6 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
for (SyncUnit *unit in self.selectedUnits) { for (SyncUnit *unit in self.selectedUnits) {
[dictArray addObject:[self dictionaryFromUnit:unit]]; [dictArray addObject:[self dictionaryFromUnit:unit]];
} }
[LocalStorage saveArray:dictArray forKey:@"SELECTED_OFFLINE_UNITS"];
[self showOfflineUnit]; [self showOfflineUnit];
} }
......
...@@ -670,7 +670,7 @@ static NSString * const kLastOfflineSyncDateKey = @"LAST_OFFLINE_SYNC_DATE"; ...@@ -670,7 +670,7 @@ static NSString * const kLastOfflineSyncDateKey = @"LAST_OFFLINE_SYNC_DATE";
} }
- (NSInteger)loadOfflineUnitCount { - (NSInteger)loadOfflineUnitCount {
NSArray *units = [LocalStorage loadArrayForKey:@"SELECTED_OFFLINE_UNITS"]; NSArray *units = [LocalStorage loadArrayForKey:kSyncSelectedUnitsKey];
return units.count; return units.count;
} }
...@@ -714,5 +714,4 @@ static NSString * const kLastOfflineSyncDateKey = @"LAST_OFFLINE_SYNC_DATE"; ...@@ -714,5 +714,4 @@ static NSString * const kLastOfflineSyncDateKey = @"LAST_OFFLINE_SYNC_DATE";
self.yesBtn.alpha = enabled ? 1.0 : 0.5; self.yesBtn.alpha = enabled ? 1.0 : 0.5;
} }
@end @end
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
return; return;
} }
NSURL *url = [APIConfig urlWithPath:@"/owner/plan/getAccessItem"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getAccessItem"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
} }
// ✅ Construct URL (with token) // ✅ Construct URL (with token)
NSURL *url = [APIConfig urlWithPath:@"/owner/plan/getLocationByUnit"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getLocationByUnit"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -177,7 +177,7 @@ ...@@ -177,7 +177,7 @@
return; return;
} }
NSURL *url = [APIConfig urlWithPath:@"/issue/getGeneralSettingByLocation"]; NSURL *url = [APIConfig urlWithPath:@"/framework/issue/getGeneralSettingByLocation"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -269,7 +269,7 @@ ...@@ -269,7 +269,7 @@
images:(NSArray<UIImage *> * _Nullable)images images:(NSArray<UIImage *> * _Nullable)images
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion { completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/addIssue"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/addIssue"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -361,7 +361,7 @@ ...@@ -361,7 +361,7 @@
images:(NSArray<UIImage *> * _Nullable)images images:(NSArray<UIImage *> * _Nullable)images
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion{ completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion{
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/updateIssue"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/updateIssue"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -470,7 +470,7 @@ ...@@ -470,7 +470,7 @@
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/appointment/getSlot"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/appointment/getSlot"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -544,7 +544,7 @@ ...@@ -544,7 +544,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/plan/getUnitInfo"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getUnitInfo"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -614,7 +614,7 @@ ...@@ -614,7 +614,7 @@
+ (void)submitAppointment:(NSDictionary *)appointmentData + (void)submitAppointment:(NSDictionary *)appointmentData
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion { completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
NSURL *url = [APIConfig urlWithPath:@"/owner/appointment/makeAppointment"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/appointment/makeAppointment"];
NSLog(@"🌍 SUBMIT (NO REP) URL: %@", url.absoluteString); NSLog(@"🌍 SUBMIT (NO REP) URL: %@", url.absoluteString);
NSLog(@"📦 SUBMIT (NO REP) Body JSON: %@", appointmentData); NSLog(@"📦 SUBMIT (NO REP) Body JSON: %@", appointmentData);
...@@ -673,7 +673,7 @@ ...@@ -673,7 +673,7 @@
+ (void)submitRepresentativeAppointment:(NSDictionary *)repData + (void)submitRepresentativeAppointment:(NSDictionary *)repData
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion { completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
NSURL *url = [APIConfig urlWithPath:@"/owner/appointment/makeAppointment"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/appointment/makeAppointment"];
NSLog(@"🌍 SUBMIT URL: %@", url.absoluteString); NSLog(@"🌍 SUBMIT URL: %@", url.absoluteString);
// Create request // Create request
...@@ -743,7 +743,7 @@ ...@@ -743,7 +743,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/appointment/cancelAppointment"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/appointment/cancelAppointment"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -817,7 +817,7 @@ ...@@ -817,7 +817,7 @@
return; return;
} }
NSURL *url = [APIConfig urlWithPath:@"/owner/plan/getIssueUpdateAppointmentInfo"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getIssueUpdateAppointmentInfo"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -883,7 +883,7 @@ ...@@ -883,7 +883,7 @@
return; return;
} }
// ✅ Keep token in URL // ✅ Keep token in URL
NSURL *url = [APIConfig urlWithPath:@"/clientAnnouncement"]; NSURL *url = [APIConfig urlWithPath:@"/framework/clientAnnouncement"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -960,7 +960,7 @@ ...@@ -960,7 +960,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/getIssueHistory"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/getIssueHistory"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1033,7 +1033,7 @@ ...@@ -1033,7 +1033,7 @@
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/addInfo"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/addInfo"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1103,7 +1103,7 @@ ...@@ -1103,7 +1103,7 @@
mediaType:(NSString *)mediaType mediaType:(NSString *)mediaType
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion { completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/addInfo"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/addInfo"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1218,7 +1218,7 @@ ...@@ -1218,7 +1218,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/getIssue"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/getIssue"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1294,7 +1294,7 @@ ...@@ -1294,7 +1294,7 @@
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/voidIssue"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/voidIssue"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1377,7 +1377,7 @@ ...@@ -1377,7 +1377,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/deleteIssue"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/deleteIssue"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1451,7 +1451,7 @@ ...@@ -1451,7 +1451,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/plan/getCommonArea"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/plan/getCommonArea"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1525,7 +1525,7 @@ ...@@ -1525,7 +1525,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/issue/getGeneralSetting"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/issue/getGeneralSetting"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1599,7 +1599,7 @@ ...@@ -1599,7 +1599,7 @@
// return; // return;
// } // }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/issue/getGeneralSettingByUnit"]; NSURL *url = [APIConfig urlWithPath:@"/framework/issue/getGeneralSettingByUnit"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1669,7 +1669,7 @@ ...@@ -1669,7 +1669,7 @@
return; return;
} }
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/project/listProject"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/project/listProject"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
...@@ -1739,7 +1739,7 @@ ...@@ -1739,7 +1739,7 @@
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion { completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
// ✅ URL // ✅ URL
NSURL *url = [APIConfig urlWithPath:@"/owner/offline/syncImageArray"]; NSURL *url = [APIConfig urlWithPath:@"/framework/owner/offline/syncImageArray"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; request.HTTPMethod = @"POST";
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
#import "LocalStorage.h" #import "LocalStorage.h"
#import "NetworkManager.h" #import "NetworkManager.h"
static NSString *kBaseURL = @"https://kitadev.commudesk.com/api"; static NSString *kBaseURL = @"https://sptest.commudesk.com/api";
static NSString *kDrawingPlanId = @""; static NSString *kDrawingPlanId = @"";
static NSString *kProjectId = @""; static NSString *kProjectId = @"";
static NSString *kAuthToken = @"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA"; static NSString *kAuthToken = @"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZSI6InNlcnZlci10by1zZXJ2ZXIiLCJmcmFtZXdvcmstYXBpIjp0cnVlLCJjb21wYW55X2NvZGUiOiJTUFQiLCJzdWIiOjE1NTcsImlzcyI6Imh0dHBzOi8vc3B0ZXN0LmNvbW11ZGVzay5jb20vYXBpL2ZyYW1ld29yay9vd25lci9hdXRoL2NsaWVudF9hdXRoZW50aWNhdGlvbiIsImlhdCI6MTc2Nzc1MjU5OSwiZXhwIjoyMDgzMzIyMTE5LCJuYmYiOjE3Njc3NTI1OTksImp0aSI6IktEcmhmSXgzeWU0WmxaUEYifQ.Bv4ZSjGRm9YYOjGItLSV_3wS7grKuPTabL60BFnp88o";
static NSString *kClientId = @"3"; static NSString *kClientId = @"3";
@implementation APIConfig @implementation APIConfig
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
@interface QmsDashboardView : UIView @interface QmsDashboardView : UIView
@property (nonatomic, strong) UIViewController *dashboardVC; @property (nonatomic, strong) UIViewController *dashboardVC;
@property (nonatomic, assign) BOOL didSetupVC; @property (nonatomic, assign) BOOL didSetupVC;
// New props
@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, copy) RCTDirectEventBlock onClose;
@end @end
@implementation QmsDashboardView @implementation QmsDashboardView
...@@ -19,6 +21,12 @@ ...@@ -19,6 +21,12 @@
_dashboardVC = [QmsPluginUI makeViewController]; _dashboardVC = [QmsPluginUI makeViewController];
_didSetupVC = NO; _didSetupVC = NO;
_dashboardVC.view.backgroundColor = [UIColor whiteColor]; _dashboardVC.view.backgroundColor = [UIColor whiteColor];
// Listen for native dashboard close notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleDashboardClose:)
name:@"QmsDashboardDidCloseNotification"
object:nil];
} }
return self; return self;
} }
...@@ -28,6 +36,10 @@ ...@@ -28,6 +36,10 @@
if (self.window && !_didSetupVC) { if (self.window && !_didSetupVC) {
UIViewController *parentVC = [UIApplication sharedApplication].keyWindow.rootViewController; UIViewController *parentVC = [UIApplication sharedApplication].keyWindow.rootViewController;
if (parentVC) { if (parentVC) {
// 1️⃣ create VC with props
_dashboardVC = [QmsPluginUI makeViewController];
[parentVC addChildViewController:_dashboardVC]; [parentVC addChildViewController:_dashboardVC];
_dashboardVC.view.frame = parentVC.view.bounds; _dashboardVC.view.frame = parentVC.view.bounds;
_dashboardVC.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _dashboardVC.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
...@@ -35,14 +47,34 @@ ...@@ -35,14 +47,34 @@
[_dashboardVC didMoveToParentViewController:parentVC]; [_dashboardVC didMoveToParentViewController:parentVC];
_didSetupVC = YES; _didSetupVC = YES;
// Forward props once the VC is added // 2️⃣ forward props again if needed
[self forwardPropsToVC]; [self forwardPropsToVC];
} }
} }
} }
#pragma mark - Prop Setters - (void)handleDashboardClose:(NSNotification *)note {
// 1️⃣ Notify JS
if (self.onClose) {
self.onClose(@{});
}
// 2️⃣ Clean up the native view controller
[self cleanupDashboard];
}
- (void)cleanupDashboard {
if (!_dashboardVC) return;
[_dashboardVC willMoveToParentViewController:nil];
[_dashboardVC.view removeFromSuperview];
[_dashboardVC removeFromParentViewController];
_dashboardVC = nil;
_didSetupVC = NO;
}
#pragma mark - Prop Setters
- (void)setClientID:(NSString *)ClientID { - (void)setClientID:(NSString *)ClientID {
_ClientID = [ClientID copy]; _ClientID = [ClientID copy];
[self forwardProp:@"ClientID" value:_ClientID]; [self forwardProp:@"ClientID" value:_ClientID];
...@@ -59,7 +91,6 @@ ...@@ -59,7 +91,6 @@
} }
#pragma mark - Forward Props via KVC #pragma mark - Forward Props via KVC
- (void)forwardProp:(NSString *)key value:(NSString *)value { - (void)forwardProp:(NSString *)key value:(NSString *)value {
if (_dashboardVC && [_dashboardVC respondsToSelector:NSSelectorFromString(key)]) { if (_dashboardVC && [_dashboardVC respondsToSelector:NSSelectorFromString(key)]) {
@try { @try {
...@@ -76,6 +107,11 @@ ...@@ -76,6 +107,11 @@
[self forwardProp:@"user_token" value:_user_token]; [self forwardProp:@"user_token" value:_user_token];
} }
- (void)removeFromSuperview {
[self cleanupDashboard];
[super removeFromSuperview];
}
@end @end
@interface QmsDashboardViewManager : RCTViewManager @interface QmsDashboardViewManager : RCTViewManager
......
...@@ -8,32 +8,32 @@ ...@@ -8,32 +8,32 @@
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string> <string>ios-arm64</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
<dict> <dict>
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64</string> <string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
</array> </array>
<key>CFBundlePackageType</key> <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