Commit c8fb728f authored by Wei Han's avatar Wei Han

code update

parent 3dd910fa
......@@ -217,7 +217,13 @@
// 🔹 Append images
if (images.count > 0) {
for (int i = 0; i < images.count; i++) {
UIImage *image = images[i];
id maybeImage = images[i];
if (![maybeImage isKindOfClass:[UIImage class]]) {
NSLog(@"⚠️ Skipping non-UIImage at index %d: %@", i, maybeImage);
continue; // skip invalid entries
}
UIImage *image = (UIImage *)maybeImage;
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
if (!imageData) continue;
......
......@@ -206,7 +206,7 @@
[content addSubview:forLabel];
[forLabel.topAnchor constraintEqualToAnchor:content.topAnchor constant:spacing].active = YES;
[forLabel.leadingAnchor constraintEqualToAnchor:content.leadingAnchor constant:20].active = YES;
// 🧩 Build dynamic text safely
NSString *unitText = @"";
if (self.projectName && self.projectCode) {
......@@ -240,12 +240,14 @@
[locationContainer.trailingAnchor constraintEqualToAnchor:content.trailingAnchor constant:-20],
[locationContainer.heightAnchor constraintEqualToConstant:44],
]];
lastView = locationContainer;
// === Location Field (read-only) ===
UITextField *locationField = [[UITextField alloc] init];
locationField.translatesAutoresizingMaskIntoConstraints = NO;
locationField.text = self.selectedLocationName ?: @"Select location";
locationField.font = [UIFont systemFontOfSize:15];
locationField.textColor = [UIColor blackColor];
locationField.enabled = NO;
[locationContainer addSubview:locationField];
self.locationField = locationField;
......@@ -257,22 +259,22 @@
]];
// === Reselect Button (inside the container, right-aligned) ===
UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
[reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
[reselectBtn setTitleColor:[UIColor colorWithRed:0/255.0 green:109/255.0 blue:141/255.0 alpha:1]
forState:UIControlStateNormal];
reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
[locationContainer addSubview:reselectBtn];
[NSLayoutConstraint activateConstraints:@[
[reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
[reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
// shrink locationField width so it doesn’t overlap
[locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
]];
// UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
// reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
// [reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
// [reselectBtn setTitleColor:[UIColor colorWithRed:0/255.0 green:109/255.0 blue:141/255.0 alpha:1]
// forState:UIControlStateNormal];
// reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
// [reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
// [locationContainer addSubview:reselectBtn];
//
// [NSLayoutConstraint activateConstraints:@[
// [reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
// [reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
//
// // shrink locationField width so it doesn’t overlap
// [locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
// ]];
// Category, Type, Issue — dropdown style
NSArray *titles = @[@"*Category", @"*Type", @"*Issue"];
......@@ -336,7 +338,9 @@
comment.layer.borderWidth = 1.0;
comment.layer.cornerRadius = 8;
comment.layer.borderColor = [UIColor lightGrayColor].CGColor;
comment.backgroundColor = [UIColor whiteColor];
comment.font = [UIFont systemFontOfSize:15];
comment.textColor = [UIColor blackColor];
[content addSubview:comment];
[NSLayoutConstraint activateConstraints:@[
[comment.topAnchor constraintEqualToAnchor:commentLabel.bottomAnchor constant:8],
......@@ -381,7 +385,7 @@
[submit setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
submit.titleLabel.font = [UIFont boldSystemFontOfSize:16];
submit.layer.cornerRadius = 8;
[submit addTarget:self action:@selector(handleSubmit) forControlEvents:UIControlEventTouchUpInside];
[submit addTarget:self action:@selector(handleSubmitTap) forControlEvents:UIControlEventTouchUpInside];
[content addSubview:submit];
[NSLayoutConstraint activateConstraints:@[
[submit.topAnchor constraintEqualToAnchor:lastView.bottomAnchor constant:spacing],
......@@ -391,7 +395,12 @@
]];
lastView = submit;
[content.bottomAnchor constraintEqualToAnchor:lastView.bottomAnchor constant:spacing].active = YES;
// 👇 Add tap gesture to dismiss keyboard
UITapGestureRecognizer *tapToDismiss = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(dismissKeyboard)];
tapToDismiss.cancelsTouchesInView = NO; // ensures buttons still respond
[self.scrollView addGestureRecognizer:tapToDismiss];
}
- (UILabel *)makeLabelWithText:(NSString *)text bold:(BOOL)bold size:(CGFloat)size {
......@@ -740,40 +749,133 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)handleSubmit {
NSLog(@"Calling addIssue API:\n planID: %@\n locationID: %@\n selectedIssueID: %@\n XCoordinates: %f\n YCoordinates: %f\n commentField: %@",
self.planID,
self.locationID,
self.selectedIssueID,
self.planX,
self.planY,
self.commentField);
- (void)handleSubmitTap {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Confirm Submission"
message:@"Are you sure you want to submit this issue?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"Submit"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[self performSubmit]; // 👈 call your existing submission logic here
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil];
[alert addAction:cancelAction];
[alert addAction:confirmAction];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)performSubmit {
NSLog(@"Calling addIssue API:\n planID: %@\n locationID: %@\n selectedIssueID: %@\n XCoordinates: %f\n YCoordinates: %f\n commentField: %@",
self.planID,
self.locationID,
self.selectedIssueID,
self.planX,
self.planY,
self.commentField.text);
NSDictionary *issueData = @{
@"plan_id": self.planID ?: @"0",
@"location_id": self.locationID ?: @"0",
@"issue_setting_id": self.selectedIssueID ?: @"",
@"position_x": [NSString stringWithFormat:@"%f", self.planX ?: 0.0],
@"position_y": [NSString stringWithFormat:@"%f", self.planY ?: 0.0],
@"comment": self.commentField ?: @"",
@"comment": self.commentField.text ?: @"",
@"os": @"AND"
};
[AddIssueAPIClient submitAddIssue:issueData
images:self.uploadedImages
completion:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
return;
}
NSDictionary *appData = response[@"AppData"];
if ([appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"✅ Issue submitted successfully!");
} else {
NSLog(@"⚠️ API Error: %@", appData[@"message"]);
}
images:self.uploadedImages
completion:^(NSDictionary *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{ // ensure UI updates happen on main thread
if (error) {
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
[self showAlertWithTitle:@"Submission Failed"
message:error.localizedDescription ?: @"An unknown error occurred."];
return;
}
NSDictionary *appData = response[@"AppData"];
if ([appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"✅ Issue submitted successfully!");
// ✅ Success alert
UIAlertController *successAlert = [UIAlertController alertControllerWithTitle:@"Issue Submitted"
message:@"Your issue has been successfully added."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
// Optionally go back or refresh dashboard
UIViewController *presenter = self.presentingViewController;
if (presenter.presentingViewController) {
[presenter.presentingViewController dismissViewControllerAnimated:YES completion:nil];
} else {
[self dismissViewControllerAnimated:YES completion:nil];
}}];
[successAlert addAction:ok];
[self presentViewController:successAlert animated:YES completion:nil];
} else {
NSString *msg = appData[@"message"] ?: @"Unexpected response from server.";
NSLog(@"⚠️ API Error: %@", msg);
[self showAlertWithTitle:@"Submission Error" message:msg];
}
});
}];
}
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
message:message
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)dismissKeyboard {
[self.view endEditing:YES];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGFloat kbHeight = kbFrame.size.height;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 0, kbHeight + 20, 0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// 👇 Optional: make sure comment field is visible
[self.scrollView scrollRectToVisible:self.commentField.frame animated:YES];
}
- (void)keyboardWillHide:(NSNotification *)notification {
self.scrollView.contentInset = UIEdgeInsetsZero;
self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
}
@end
......@@ -291,16 +291,16 @@
[self.headerView addSubview:self.backButton];
// ❓ Help button
self.helpButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.helpButton.translatesAutoresizingMaskIntoConstraints = NO;
UIImage *helpImage = [[UIImage systemImageNamed:@"questionmark.circle"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[self.helpButton setImage:helpImage forState:UIControlStateNormal];
self.helpButton.tintColor = UIColor.whiteColor;
[self.helpButton addTarget:self
action:@selector(showTutorial)
forControlEvents:UIControlEventTouchUpInside];
[self.headerView addSubview:self.helpButton];
// self.helpButton = [UIButton buttonWithType:UIButtonTypeSystem];
// self.helpButton.translatesAutoresizingMaskIntoConstraints = NO;
// UIImage *helpImage = [[UIImage systemImageNamed:@"questionmark.circle"]
// imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
// [self.helpButton setImage:helpImage forState:UIControlStateNormal];
// self.helpButton.tintColor = UIColor.whiteColor;
// [self.helpButton addTarget:self
// action:@selector(showTutorial)
// forControlEvents:UIControlEventTouchUpInside];
// [self.headerView addSubview:self.helpButton];
// 🏷 Title label (project name)
self.titleLabel = [[UILabel alloc] init];
......@@ -344,20 +344,20 @@
[self.backButton.heightAnchor constraintEqualToConstant:44],
// Help button
[self.helpButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
[self.helpButton.centerYAnchor constraintEqualToAnchor:self.backButton.centerYAnchor],
[self.helpButton.widthAnchor constraintEqualToConstant:44],
[self.helpButton.heightAnchor constraintEqualToConstant:44],
// [self.helpButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
// [self.helpButton.centerYAnchor constraintEqualToAnchor:self.backButton.centerYAnchor],
// [self.helpButton.widthAnchor constraintEqualToConstant:44],
// [self.helpButton.heightAnchor constraintEqualToConstant:44],
// Title label (below buttons, left-aligned)
[self.titleLabel.topAnchor constraintEqualToAnchor:self.backButton.bottomAnchor constant:4],
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:16],
[self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
// [self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
// Subtitle (below title, left-aligned)
[subtitleLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:2],
[subtitleLabel.leadingAnchor constraintEqualToAnchor:self.titleLabel.leadingAnchor],
[subtitleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
// [subtitleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:self.helpButton.leadingAnchor constant:-8],
]];
}
......
......@@ -52,11 +52,11 @@
[self addSubview:_unitNameLabel];
// Info button (bottom right)
_infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
_infoButton.translatesAutoresizingMaskIntoConstraints = NO;
[_infoButton setImage:[UIImage systemImageNamed:@"info.circle"] forState:UIControlStateNormal];
_infoButton.tintColor = [UIColor whiteColor];
[self addSubview:_infoButton];
// _infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
// _infoButton.translatesAutoresizingMaskIntoConstraints = NO;
// [_infoButton setImage:[UIImage systemImageNamed:@"info.circle"] forState:UIControlStateNormal];
// _infoButton.tintColor = [UIColor whiteColor];
// [self addSubview:_infoButton];
// Layout constraints
[NSLayoutConstraint activateConstraints:@[
......@@ -79,10 +79,10 @@
[_unitNameLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-16],
// Info button bottom-right
[_infoButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-16],
[_infoButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-18],
[_infoButton.widthAnchor constraintEqualToConstant:24],
[_infoButton.heightAnchor constraintEqualToConstant:24],
// [_infoButton.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-16],
// [_infoButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-18],
// [_infoButton.widthAnchor constraintEqualToConstant:24],
// [_infoButton.heightAnchor constraintEqualToConstant:24],
]];
}
......
......@@ -24,6 +24,8 @@
@property (nonatomic, strong) NSString *projectName;
@property (nonatomic, strong) UIImage *headerBackgroundImage;
@property (nonatomic, strong) NSArray *announcements;
@property (nonatomic, strong) UIView *loadingOverlay;
@property (nonatomic, strong) UIActivityIndicatorView *spinner;
@end
......@@ -47,49 +49,49 @@
self.projectCode = @"PTD197656";
self.projectName = @"Ara E`Residence Dev";
[DashboardAPIClient fetchDashboardInfo:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ fetchDashboardInfo error: %@", error.localizedDescription);
return;
}
[self refreshDashboardContent];
}
#pragma mark - Refresh Logic
- (void)refreshDashboardContent {
NSLog(@"🔁 Refreshing dashboard content...");
NSLog(@"🧩 Dashboard Info response received");
[self processDashboardResponse:data];
dispatch_group_t group = dispatch_group_create();
__block NSDictionary *dashboardData = nil;
__block NSDictionary *announcementData = nil;
// 💾 Optionally, save full JSON to a file for reference
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [docsPath stringByAppendingPathComponent:@"DashboardInfoResponse.txt"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:NSJSONWritingPrettyPrinted error:nil];
[jsonData writeToFile:filePath atomically:YES];
NSLog(@"📁 Dashboard API response saved to %@", filePath);
dispatch_group_enter(group);
[DashboardAPIClient fetchDashboardInfo:^(NSDictionary *data, NSError *error) {
if (!error) dashboardData = data;
dispatch_group_leave(group);
}];
dispatch_group_enter(group);
[DashboardAPIClient fetchAnnouncement:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ fetchAnnouncement error: %@", error.localizedDescription);
return;
}
if (!error) announcementData = data;
dispatch_group_leave(group);
}];
NSLog(@"🗞️ Announcement response received");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
if (dashboardData) [self processDashboardResponse:dashboardData];
if (announcementData) [self processAnnouncementResponse:announcementData];
NSLog(@"✅ Dashboard refresh complete");
});
}
// 🔍 Optional: Log the whole JSON structure for debugging
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"%@", jsonString);
// 💾 Save to file for offline reference
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [docsPath stringByAppendingPathComponent:@"AnnouncementResponse.txt"];
[jsonData writeToFile:filePath atomically:YES];
NSLog(@"📁 Announcement response saved to %@", filePath);
- (void)handlePullToRefresh:(UIRefreshControl *)refreshControl {
NSLog(@"🔄 Pull-to-refresh triggered");
// ✅ Process and show popup announcements
[self processAnnouncementResponse:data];
}];
[self refreshDashboardContent];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[refreshControl endRefreshing];
});
}
#pragma mark - Layout
- (void)viewDidLayoutSubviews {
NSLog(@"Header frame: %@", NSStringFromCGRect(_headerView.frame));
[super viewDidLayoutSubviews];
......@@ -105,7 +107,6 @@
}
#pragma mark - Header
- (void)setupHeader {
CGFloat headerHeight = 220.0;
_headerView = [[DashboardHeaderView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, headerHeight)];
......@@ -131,33 +132,33 @@
});
[self.view addSubview:_headerView];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeSystem];
backButton.translatesAutoresizingMaskIntoConstraints = NO;
UIImage *backImage = [[UIImage systemImageNamed:@"chevron.left"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[backButton setImage:backImage forState:UIControlStateNormal];
backButton.tintColor = [UIColor whiteColor];
[backButton addTarget:self action:@selector(handleBackButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:backButton];
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeSystem];
menuButton.translatesAutoresizingMaskIntoConstraints = NO;
UIImage *menuImage = [[UIImage systemImageNamed:@"line.3.horizontal"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[menuButton setImage:menuImage forState:UIControlStateNormal];
menuButton.tintColor = [UIColor whiteColor];
[menuButton addTarget:self action:@selector(handleMenuButtonTapped) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:menuButton];
[NSLayoutConstraint activateConstraints:@[
[backButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:8],
[backButton.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:4],
[backButton.widthAnchor constraintEqualToConstant:44],
[backButton.heightAnchor constraintEqualToConstant:44],
[menuButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-8],
[menuButton.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:4],
[menuButton.widthAnchor constraintEqualToConstant:44],
[menuButton.heightAnchor constraintEqualToConstant:44],
]];
// UIButton *backButton = [UIButton buttonWithType:UIButtonTypeSystem];
// backButton.translatesAutoresizingMaskIntoConstraints = NO;
// UIImage *backImage = [[UIImage systemImageNamed:@"chevron.left"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
// [backButton setImage:backImage forState:UIControlStateNormal];
// backButton.tintColor = [UIColor whiteColor];
// [backButton addTarget:self action:@selector(handleBackButtonTapped) forControlEvents:UIControlEventTouchUpInside];
// [self.view addSubview:backButton];
// UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeSystem];
// menuButton.translatesAutoresizingMaskIntoConstraints = NO;
// UIImage *menuImage = [[UIImage systemImageNamed:@"line.3.horizontal"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
// [menuButton setImage:menuImage forState:UIControlStateNormal];
// menuButton.tintColor = [UIColor whiteColor];
// [menuButton addTarget:self action:@selector(handleMenuButtonTapped) forControlEvents:UIControlEventTouchUpInside];
// [self.view addSubview:menuButton];
// [NSLayoutConstraint activateConstraints:@[
// [backButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:8],
// [backButton.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:4],
// [backButton.widthAnchor constraintEqualToConstant:44],
// [backButton.heightAnchor constraintEqualToConstant:44],
//
// [menuButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-8],
// [menuButton.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:4],
// [menuButton.widthAnchor constraintEqualToConstant:44],
// [menuButton.heightAnchor constraintEqualToConstant:44],
// ]];
}
- (void)handleBackButtonTapped {
......@@ -174,7 +175,6 @@
}
#pragma mark - Footer
- (void)setupFooter {
CGFloat footerHeight = 80.0;
CGFloat bottomInset = self.view.safeAreaInsets.bottom;
......@@ -241,7 +241,6 @@
}
#pragma mark - Scroll Content
- (void)setupScrollContent {
CGFloat topOffset = 220.0;
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(
......@@ -258,6 +257,17 @@
_scrollView.contentInset = UIEdgeInsetsMake(0, 0, footerHeight, 0);
_scrollView.scrollIndicatorInsets = _scrollView.contentInset;
// === 🌀 Add Pull-to-Refresh ===
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self
action:@selector(handlePullToRefresh:)
forControlEvents:UIControlEventValueChanged];
if (@available(iOS 10.0, *)) {
_scrollView.refreshControl = refreshControl;
} else {
[_scrollView addSubview:refreshControl];
}
[self.view addSubview:_scrollView];
_contentContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _scrollView.bounds.size.width, 0)];
......@@ -346,7 +356,6 @@
}
#pragma mark - Dashboard Data Processor
- (void)processDashboardResponse:(NSDictionary *)data {
NSDictionary *appData = data[@"AppData"];
NSDictionary *mainData = data[@"Data"];
......@@ -467,8 +476,6 @@
// }
}
- (void)refreshDashboardSectionsWithData:(NSDictionary *)mainData {
NSLog(@"🔄 Refreshing dashboard sections...");
......@@ -525,6 +532,7 @@
UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, 200, 24)];
title.text = @"Project Update";
title.font = [UIFont boldSystemFontOfSize:18];
title.textColor = [UIColor blackColor];
title.userInteractionEnabled = YES; // 👈 enable taps
UITapGestureRecognizer *titleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
......@@ -567,6 +575,7 @@
title.text = @"Appointments";
title.font = [UIFont boldSystemFontOfSize:18];
[section addSubview:title];
title.textColor = [UIColor blackColor];
title.userInteractionEnabled = YES; // 👈 enable taps
UITapGestureRecognizer *titleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
......@@ -604,6 +613,7 @@
title.text = @"Issue Updates";
title.font = [UIFont boldSystemFontOfSize:18];
[section addSubview:title];
title.textColor = [UIColor blackColor];
title.userInteractionEnabled = YES; // 👈 enable taps
UITapGestureRecognizer *titleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(sectionHeaderTapped:)];
......@@ -675,6 +685,7 @@
title.text = item[@"title"] ?: @"Untitled announcement";
title.numberOfLines = 3;
title.font = [UIFont boldSystemFontOfSize:16];
title.textColor = [UIColor blackColor];
[card addSubview:title];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleAnnouncementTap:)];
......@@ -730,6 +741,7 @@
timeLabel.textAlignment = NSTextAlignmentRight;
timeLabel.text = startTime;
timeLabel.font = [UIFont boldSystemFontOfSize:15];
timeLabel.textColor = [UIColor grayColor];
[card addSubview:timeLabel];
// === Description text ===
......@@ -945,7 +957,6 @@
}
#pragma mark - Individual Card Taps
- (void)handleAnnouncementTap:(UITapGestureRecognizer *)gesture {
UIView *card = gesture.view;
[self animateTapForView:card];
......@@ -973,7 +984,6 @@
}
#pragma mark - Card Factory with Tap Animation
- (UIView *)createCardWithText:(NSString *)text frame:(CGRect)frame {
UIView *card = [[UIView alloc] initWithFrame:frame];
card.backgroundColor = [UIColor whiteColor];
......@@ -997,7 +1007,6 @@
}
#pragma mark - Tap Handlers
- (void)sectionHeaderTapped:(UITapGestureRecognizer *)gesture {
UILabel *header = (UILabel *)gesture.view;
[self animateTapForView:header];
......@@ -1022,4 +1031,40 @@
}];
}
#pragma mark - Loading Overlay
- (void)showLoadingOverlay:(NSString *)message {
if (self.loadingOverlay.superview) return; // already showing
UIView *overlay = [[UIView alloc] initWithFrame:self.view.bounds];
overlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
overlay.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
spinner.center = overlay.center;
spinner.color = UIColor.whiteColor;
[spinner startAnimating];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(spinner.frame) + 16,
overlay.bounds.size.width, 30)];
label.text = message ?: @"Loading...";
label.textAlignment = NSTextAlignmentCenter;
label.textColor = UIColor.whiteColor;
label.font = [UIFont boldSystemFontOfSize:16];
[overlay addSubview:spinner];
[overlay addSubview:label];
[self.view addSubview:overlay];
self.loadingOverlay = overlay;
self.spinner = spinner;
}
- (void)hideLoadingOverlay {
[self.spinner stopAnimating];
[self.loadingOverlay removeFromSuperview];
self.loadingOverlay = nil;
self.spinner = nil;
}
@end
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