Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
weihan-plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Wei Han
weihan-plugin
Commits
09397ebc
Commit
09397ebc
authored
Nov 21, 2025
by
Wei Han
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
code update
parent
e54ac633
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
888 additions
and
108 deletions
+888
-108
AppointmentConfirmationViewController.h
...ework/Appointment/AppointmentConfirmationViewController.h
+12
-0
AppointmentConfirmationViewController.mm
...work/Appointment/AppointmentConfirmationViewController.mm
+295
-0
AppointmentDetailsViewController.h
...nFramework/Appointment/AppointmentDetailsViewController.h
+11
-0
AppointmentDetailsViewController.mm
...Framework/Appointment/AppointmentDetailsViewController.mm
+275
-0
AppointmentTimeSlotViewController.mm
...ramework/Appointment/AppointmentTimeSlotViewController.mm
+50
-94
AppointmentViewController.h
...msPluginFramework/Appointment/AppointmentViewController.h
+2
-2
AppointmentViewMoreViewController.h
...Framework/Appointment/AppointmentViewMoreViewController.h
+8
-0
AppointmentViewMoreViewController.mm
...ramework/Appointment/AppointmentViewMoreViewController.mm
+208
-0
DashboardViewController.mm
...k/QmsPluginFramework/Dashboard/DashboardViewController.mm
+27
-12
No files found.
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentConfirmationViewController.h
0 → 100644
View file @
09397ebc
// AppointmentConfirmationViewController.h
#import <UIKit/UIKit.h>
@interface
AppointmentConfirmationViewController
:
UIViewController
@property
(
nonatomic
,
strong
)
NSString
*
slotId
;
@property
(
nonatomic
,
strong
)
NSString
*
startDate
;
@property
(
nonatomic
,
strong
)
NSString
*
startTime
;
@end
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentConfirmationViewController.mm
0 → 100644
View file @
09397ebc
// AppointmentConfirmationViewController.mm
#import "AppointmentConfirmationViewController.h"
#import <WebKit/WebKit.h>
@interface AppointmentConfirmationViewController ()
// Top Bar
@property (nonatomic, strong) UIView *navBar;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *closeButton;
// Scroll
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIView *contentView;
// Summary Section
@property (nonatomic, strong) UILabel *unitLabel;
@property (nonatomic, strong) UIView *stepBanner;
@property (nonatomic, strong) UIView *summaryCard;
@property (nonatomic, strong) UILabel *appointmentTypeLabel;
@property (nonatomic, strong) UILabel *dateLabel;
@property (nonatomic, strong) UILabel *timeLabel;
// Representative Section
@property (nonatomic, strong) UIView *representativeSection;
@property (nonatomic, strong) UILabel *repTitleLabel;
@property (nonatomic, strong) UIButton *repToggleButton;
// T&C
@property (nonatomic, strong) UILabel *tcTitleLabel;
@property (nonatomic, strong) WKWebView *htmlView;
// Bottom Buttons
@property (nonatomic, strong) UIView *bottomBar;
@property (nonatomic, strong) UIButton *editButton;
@property (nonatomic, strong) UIButton *confirmButton;
// Modal Placeholder
@property (nonatomic, strong) UIView *dimOverlay;
@end
@implementation AppointmentConfirmationViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
[self setupNavBar];
[self setupScrollView];
[self setupContentUI];
[self setupBottomBar];
}
#pragma mark - Navigation Bar
- (void)setupNavBar {
self.navBar = [[UIView alloc] init];
self.navBar.backgroundColor = [UIColor colorWithRed:0 green:0.45 blue:0.55 alpha:1];
self.navBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.navBar];
// Title
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.text = @"Make Appointment";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.font = [UIFont boldSystemFontOfSize:18];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.navBar addSubview:self.titleLabel];
// Close Button
self.closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.closeButton setImage:[UIImage imageNamed:@"icon_white_cancel"] forState:UIControlStateNormal];
self.closeButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.navBar addSubview:self.closeButton];
// Constraints
[NSLayoutConstraint activateConstraints:@[
[self.navBar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.navBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.navBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.navBar.heightAnchor constraintEqualToConstant:48],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.navBar.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
[self.closeButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:12],
[self.closeButton.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
[self.closeButton.widthAnchor constraintEqualToConstant:30],
[self.closeButton.heightAnchor constraintEqualToConstant:30],
]];
}
#pragma mark - ScrollView
- (void)setupScrollView {
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.scrollView];
self.contentView = [[UIView alloc] init];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.scrollView addSubview:self.contentView];
[NSLayoutConstraint activateConstraints:@[
[self.scrollView.topAnchor constraintEqualToAnchor:self.navBar.bottomAnchor],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[self.contentView.topAnchor constraintEqualToAnchor:self.scrollView.topAnchor],
[self.contentView.leadingAnchor constraintEqualToAnchor:self.scrollView.leadingAnchor],
[self.contentView.trailingAnchor constraintEqualToAnchor:self.scrollView.trailingAnchor],
[self.contentView.bottomAnchor constraintEqualToAnchor:self.scrollView.bottomAnchor],
[self.contentView.widthAnchor constraintEqualToAnchor:self.scrollView.widthAnchor],
]];
}
#pragma mark - Main UI
- (void)setupContentUI {
// Unit Label
self.unitLabel = [[UILabel alloc] init];
self.unitLabel.text = @"ProjectName, Unit 12-34";
self.unitLabel.font = [UIFont boldSystemFontOfSize:20];
self.unitLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.unitLabel];
// Step Banner
self.stepBanner = [[UIView alloc] init];
self.stepBanner.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1];
self.stepBanner.layer.cornerRadius = 12;
self.stepBanner.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.stepBanner];
UILabel *stepLabel = [[UILabel alloc] init];
stepLabel.text = @"Step 3: Appointment Summary";
stepLabel.font = [UIFont systemFontOfSize:15];
stepLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.stepBanner addSubview:stepLabel];
// Summary Card
self.summaryCard = [[UIView alloc] init];
self.summaryCard.backgroundColor = [UIColor colorWithRed:0 green:0.23 blue:0.30 alpha:1];
self.summaryCard.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.summaryCard];
self.appointmentTypeLabel = [[UILabel alloc] init];
self.appointmentTypeLabel.text = @"Inspection";
self.appointmentTypeLabel.textColor = UIColor.whiteColor;
self.appointmentTypeLabel.font = [UIFont boldSystemFontOfSize:22];
self.appointmentTypeLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.summaryCard addSubview:self.appointmentTypeLabel];
self.dateLabel = [[UILabel alloc] init];
self.dateLabel.text = @"20 Jan 2025";
self.dateLabel.textColor = UIColor.whiteColor;
self.dateLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.summaryCard addSubview:self.dateLabel];
self.timeLabel = [[UILabel alloc] init];
self.timeLabel.text = @"09:00 AM";
self.timeLabel.textColor = UIColor.whiteColor;
self.timeLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.summaryCard addSubview:self.timeLabel];
// Representative Section
self.representativeSection = [[UIView alloc] init];
self.representativeSection.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.representativeSection];
self.repTitleLabel = [[UILabel alloc] init];
self.repTitleLabel.text = @"Representative Attending?";
self.repTitleLabel.font = [UIFont boldSystemFontOfSize:17];
self.repTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.repToggleButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.repToggleButton.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1];
self.repToggleButton.layer.cornerRadius = 14;
self.repToggleButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.representativeSection addSubview:self.repTitleLabel];
[self.representativeSection addSubview:self.repToggleButton];
// Terms & Conditions
self.tcTitleLabel = [[UILabel alloc] init];
self.tcTitleLabel.text = @"Terms & Conditions";
self.tcTitleLabel.font = [UIFont boldSystemFontOfSize:16];
self.tcTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.tcTitleLabel];
self.htmlView = [[WKWebView alloc] init];
self.htmlView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.htmlView];
// Layout
[NSLayoutConstraint activateConstraints:@[
[self.unitLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:20],
[self.unitLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20],
[self.stepBanner.topAnchor constraintEqualToAnchor:self.unitLabel.bottomAnchor constant:20],
[self.stepBanner.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.stepBanner.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[self.stepBanner.heightAnchor constraintEqualToConstant:50],
[stepLabel.centerYAnchor constraintEqualToAnchor:self.stepBanner.centerYAnchor],
[stepLabel.leadingAnchor constraintEqualToAnchor:self.stepBanner.leadingAnchor constant:12],
// Summary Card
[self.summaryCard.topAnchor constraintEqualToAnchor:self.stepBanner.bottomAnchor constant:20],
[self.summaryCard.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
[self.summaryCard.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
[self.appointmentTypeLabel.topAnchor constraintEqualToAnchor:self.summaryCard.topAnchor constant:20],
[self.appointmentTypeLabel.leadingAnchor constraintEqualToAnchor:self.summaryCard.leadingAnchor constant:20],
[self.dateLabel.topAnchor constraintEqualToAnchor:self.appointmentTypeLabel.bottomAnchor constant:16],
[self.dateLabel.leadingAnchor constraintEqualToAnchor:self.summaryCard.leadingAnchor constant:20],
[self.timeLabel.topAnchor constraintEqualToAnchor:self.dateLabel.bottomAnchor constant:8],
[self.timeLabel.leadingAnchor constraintEqualToAnchor:self.summaryCard.leadingAnchor constant:20],
[self.timeLabel.bottomAnchor constraintEqualToAnchor:self.summaryCard.bottomAnchor constant:-20],
// Representative
[self.representativeSection.topAnchor constraintEqualToAnchor:self.summaryCard.bottomAnchor constant:30],
[self.representativeSection.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20],
[self.representativeSection.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-20],
[self.representativeSection.heightAnchor constraintEqualToConstant:50],
[self.repTitleLabel.centerYAnchor constraintEqualToAnchor:self.representativeSection.centerYAnchor],
[self.repTitleLabel.leadingAnchor constraintEqualToAnchor:self.representativeSection.leadingAnchor],
[self.repToggleButton.centerYAnchor constraintEqualToAnchor:self.representativeSection.centerYAnchor],
[self.repToggleButton.trailingAnchor constraintEqualToAnchor:self.representativeSection.trailingAnchor],
[self.repToggleButton.widthAnchor constraintEqualToConstant:28],
[self.repToggleButton.heightAnchor constraintEqualToConstant:28],
// Terms & Conditions
[self.tcTitleLabel.topAnchor constraintEqualToAnchor:self.representativeSection.bottomAnchor constant:30],
[self.tcTitleLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20],
[self.htmlView.topAnchor constraintEqualToAnchor:self.tcTitleLabel.bottomAnchor constant:12],
[self.htmlView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:20],
[self.htmlView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-20],
[self.htmlView.heightAnchor constraintEqualToConstant:200],
[self.htmlView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-40],
]];
}
#pragma mark - Bottom Bar
- (void)setupBottomBar {
self.bottomBar = [[UIView alloc] init];
self.bottomBar.backgroundColor = UIColor.whiteColor;
self.bottomBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.bottomBar];
self.editButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.editButton setTitle:@"Edit" forState:UIControlStateNormal];
self.editButton.layer.borderColor = [UIColor colorWithRed:0 green:0.45 blue:0.55 alpha:1].CGColor;
self.editButton.layer.borderWidth = 1;
self.editButton.layer.cornerRadius = 20;
self.editButton.translatesAutoresizingMaskIntoConstraints = NO;
self.confirmButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.confirmButton setTitle:@"Confirm" forState:UIControlStateNormal];
self.confirmButton.backgroundColor = [UIColor colorWithRed:0 green:0.45 blue:0.55 alpha:1];
[self.confirmButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
self.confirmButton.layer.cornerRadius = 20;
self.confirmButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.bottomBar addSubview:self.editButton];
[self.bottomBar addSubview:self.confirmButton];
[NSLayoutConstraint activateConstraints:@[
[self.bottomBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.bottomBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.bottomBar.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
[self.bottomBar.heightAnchor constraintEqualToConstant:70],
[self.editButton.leadingAnchor constraintEqualToAnchor:self.bottomBar.leadingAnchor constant:20],
[self.editButton.centerYAnchor constraintEqualToAnchor:self.bottomBar.centerYAnchor],
[self.editButton.widthAnchor constraintEqualToAnchor:self.bottomBar.widthAnchor multiplier:0.45],
[self.editButton.heightAnchor constraintEqualToConstant:48],
[self.confirmButton.trailingAnchor constraintEqualToAnchor:self.bottomBar.trailingAnchor constant:-20],
[self.confirmButton.centerYAnchor constraintEqualToAnchor:self.bottomBar.centerYAnchor],
[self.confirmButton.widthAnchor constraintEqualToAnchor:self.bottomBar.widthAnchor multiplier:0.45],
[self.confirmButton.heightAnchor constraintEqualToConstant:48],
]];
}
@end
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentDetailsViewController.h
0 → 100644
View file @
09397ebc
// AppointmentDetailsViewController.h
#import <UIKit/UIKit.h>
@interface
AppointmentDetailsViewController
:
UIViewController
@property
(
nonatomic
,
strong
)
NSString
*
appointmentID
;
@property
(
nonatomic
,
strong
)
NSDictionary
*
appointmentData
;
@end
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentDetailsViewController.mm
0 → 100644
View file @
09397ebc
// AppointmentDetailsViewController.mm
#import "AppointmentDetailsViewController.h"
#import <WebKit/WebKit.h>
@interface AppointmentDetailsViewController ()
// UI
@property (nonatomic, strong) UIView *navBar;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIView *contentView;
@property (nonatomic, strong) UIView *statusBanner;
@property (nonatomic, strong) UILabel *statusLabel;
@property (nonatomic, strong) UILabel *reasonLabel;
@property (nonatomic, strong) UIView *summaryCard;
@property (nonatomic, strong) UIView *repCard;
@property (nonatomic, strong) UIView *buttonSection;
@property (nonatomic, strong) UIView *loadingOverlay;
@end
@implementation AppointmentDetailsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
[self setupNavBar];
[self setupScrollView];
[self setupStatusBanner];
[self setupSummaryCard];
[self setupRepresentativeCard];
[self setupButtonSection];
[self setupLoadingOverlay];
// load appointment details
[self loadAppointmentDetails];
}
#pragma mark - Navigation Bar
- (void)setupNavBar {
self.navBar = [[UIView alloc] init];
self.navBar.backgroundColor = [UIColor colorWithRed:0 green:0.45 blue:0.55 alpha:1];
self.navBar.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.navBar];
self.titleLabel = [[UILabel alloc] init];
self.titleLabel.text = @"Appointment Details";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.font = [UIFont boldSystemFontOfSize:17];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.navBar addSubview:self.titleLabel];
self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.backButton setImage:[UIImage imageNamed:@"icon_white_back"] forState:UIControlStateNormal];
[self.backButton addTarget:self action:@selector(backTapped) forControlEvents:UIControlEventTouchUpInside];
self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
[self.navBar addSubview:self.backButton];
[NSLayoutConstraint activateConstraints:@[
[self.navBar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.navBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.navBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.navBar.heightAnchor constraintEqualToConstant:50],
[self.backButton.leadingAnchor constraintEqualToAnchor:self.navBar.leadingAnchor constant:10],
[self.backButton.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
[self.backButton.widthAnchor constraintEqualToConstant:30],
[self.backButton.heightAnchor constraintEqualToConstant:30],
[self.titleLabel.centerXAnchor constraintEqualToAnchor:self.navBar.centerXAnchor],
[self.titleLabel.centerYAnchor constraintEqualToAnchor:self.navBar.centerYAnchor],
]];
}
#pragma mark - ScrollView
- (void)setupScrollView {
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
self.contentView = [[UIView alloc] init];
self.contentView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.scrollView];
[self.scrollView addSubview:self.contentView];
[NSLayoutConstraint activateConstraints:@[
[self.scrollView.topAnchor constraintEqualToAnchor:self.navBar.bottomAnchor],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
[self.contentView.topAnchor constraintEqualToAnchor:self.scrollView.topAnchor],
[self.contentView.leadingAnchor constraintEqualToAnchor:self.scrollView.leadingAnchor],
[self.contentView.trailingAnchor constraintEqualToAnchor:self.scrollView.trailingAnchor],
[self.contentView.bottomAnchor constraintEqualToAnchor:self.scrollView.bottomAnchor],
[self.contentView.widthAnchor constraintEqualToAnchor:self.scrollView.widthAnchor],
]];
}
#pragma mark - Status Banner
- (void)setupStatusBanner {
self.statusBanner = [[UIView alloc] init];
self.statusBanner.layer.cornerRadius = 12;
self.statusBanner.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.statusBanner];
self.statusLabel = [[UILabel alloc] init];
self.statusLabel.font = [UIFont boldSystemFontOfSize:18];
self.statusLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.statusBanner addSubview:self.statusLabel];
self.reasonLabel = [[UILabel alloc] init];
self.reasonLabel.font = [UIFont systemFontOfSize:14];
self.reasonLabel.numberOfLines = 0;
self.reasonLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.statusBanner addSubview:self.reasonLabel];
[NSLayoutConstraint activateConstraints:@[
[self.statusBanner.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:20],
[self.statusBanner.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.statusBanner.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[self.statusLabel.topAnchor constraintEqualToAnchor:self.statusBanner.topAnchor constant:16],
[self.statusLabel.leadingAnchor constraintEqualToAnchor:self.statusBanner.leadingAnchor constant:16],
[self.reasonLabel.topAnchor constraintEqualToAnchor:self.statusLabel.bottomAnchor constant:8],
[self.reasonLabel.leadingAnchor constraintEqualToAnchor:self.statusBanner.leadingAnchor constant:16],
[self.reasonLabel.trailingAnchor constraintEqualToAnchor:self.statusBanner.trailingAnchor constant:-16],
[self.reasonLabel.bottomAnchor constraintEqualToAnchor:self.statusBanner.bottomAnchor constant:-16],
]];
}
#pragma mark - Appointment Summary Card
- (void)setupSummaryCard {
self.summaryCard = [[UIView alloc] init];
self.summaryCard.backgroundColor = UIColor.whiteColor;
self.summaryCard.layer.cornerRadius = 12;
self.summaryCard.layer.borderWidth = 1;
self.summaryCard.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:1].CGColor;
self.summaryCard.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.summaryCard];
UILabel *title = [[UILabel alloc] init];
title.text = @"Appointment Summary";
title.font = [UIFont boldSystemFontOfSize:16];
title.translatesAutoresizingMaskIntoConstraints = NO;
[self.summaryCard addSubview:title];
[NSLayoutConstraint activateConstraints:@[
[self.summaryCard.topAnchor constraintEqualToAnchor:self.statusBanner.bottomAnchor constant:20],
[self.summaryCard.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.summaryCard.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[title.topAnchor constraintEqualToAnchor:self.summaryCard.topAnchor constant:16],
[title.leadingAnchor constraintEqualToAnchor:self.summaryCard.leadingAnchor constant:16],
]];
// Add additional appointment fields later in applyAppointmentDataToUI
}
#pragma mark - Representative Card
- (void)setupRepresentativeCard {
self.repCard = [[UIView alloc] init];
self.repCard.backgroundColor = UIColor.whiteColor;
self.repCard.layer.cornerRadius = 12;
self.repCard.layer.borderColor = [UIColor colorWithWhite:0.9 alpha:1].CGColor;
self.repCard.layer.borderWidth = 1;
self.repCard.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.repCard];
UILabel *title = [[UILabel alloc] init];
title.text = @"Representative";
title.font = [UIFont boldSystemFontOfSize:16];
title.translatesAutoresizingMaskIntoConstraints = NO;
[self.repCard addSubview:title];
[NSLayoutConstraint activateConstraints:@[
[self.repCard.topAnchor constraintEqualToAnchor:self.summaryCard.bottomAnchor constant:20],
[self.repCard.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
[self.repCard.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
[title.topAnchor constraintEqualToAnchor:self.repCard.topAnchor constant:16],
[title.leadingAnchor constraintEqualToAnchor:self.repCard.leadingAnchor constant:16],
]];
}
#pragma mark - Buttons Section
- (void)setupButtonSection {
self.buttonSection = [[UIView alloc] init];
self.buttonSection.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:self.buttonSection];
[NSLayoutConstraint activateConstraints:@[
[self.buttonSection.topAnchor constraintEqualToAnchor:self.repCard.bottomAnchor constant:30],
[self.buttonSection.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor],
[self.buttonSection.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor],
[self.buttonSection.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-40],
[self.buttonSection.heightAnchor constraintEqualToConstant:200], // dynamic later
]];
}
#pragma mark - Loading Overlay
- (void)setupLoadingOverlay {
self.loadingOverlay = [[UIView alloc] initWithFrame:self.view.bounds];
self.loadingOverlay.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
self.loadingOverlay.hidden = YES;
UIActivityIndicatorView *spin = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
spin.color = UIColor.whiteColor;
spin.center = self.loadingOverlay.center;
[self.loadingOverlay addSubview:spin];
[self.view addSubview:self.loadingOverlay];
[spin startAnimating];
}
#pragma mark - Load Data
- (void)loadAppointmentDetails {
self.loadingOverlay.hidden = NO;
// TODO: call your API here
// Then call:
// [self applyAppointmentDataToUI];
}
#pragma mark - Apply Data
- (void)applyAppointmentDataToUI {
self.loadingOverlay.hidden = YES;
NSString *status = self.appointmentData[@"appointment_status"];
if ([status isEqualToString:@"Pending"]) {
self.statusBanner.backgroundColor = [UIColor colorWithRed:0.95 green:0.8 blue:0.2 alpha:1];
} else if ([status isEqualToString:@"Approved"]) {
self.statusBanner.backgroundColor = [UIColor colorWithRed:0 green:0.7 blue:0.3 alpha:1];
} else if ([status isEqualToString:@"Rejected"]) {
self.statusBanner.backgroundColor = [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1];
} else {
self.statusBanner.backgroundColor = [UIColor lightGrayColor];
}
self.statusLabel.text = status;
self.reasonLabel.text = self.appointmentData[@"rejected_reason"];
// TODO: fill summary card fields
// TODO: fill representative card fields
// TODO: build action buttons based on status
}
#pragma mark - Actions
- (void)backTapped {
[self.navigationController popViewControllerAnimated:YES];
}
@end
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentTimeSlotViewController.mm
View file @
09397ebc
// AppointmentTimeSlotViewController.mm
// AppointmentTimeSlotViewController.mm
#import "AppointmentTimeSlotViewController.h"
#import "AppointmentTimeSlotViewController.h"
#import "AppointmentConfirmationViewController.h"
@interface AppointmentTimeSlotViewController ()
@interface AppointmentTimeSlotViewController ()
...
@@ -134,7 +135,7 @@
...
@@ -134,7 +135,7 @@
[self.scrollView.topAnchor constraintEqualToAnchor:self.headerBar.bottomAnchor],
[self.scrollView.topAnchor constraintEqualToAnchor:self.headerBar.bottomAnchor],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.
view.safeAreaLayoutGuide.bottomAnchor constant:-80
] // space for footer
[self.scrollView.bottomAnchor constraintEqualToAnchor:self.
footerView.topAnchor
] // space for footer
]];
]];
UIView *container = [[UIView alloc] init];
UIView *container = [[UIView alloc] init];
...
@@ -163,46 +164,38 @@
...
@@ -163,46 +164,38 @@
[self.contentStack.bottomAnchor constraintLessThanOrEqualToAnchor:container.bottomAnchor constant:-16]
[self.contentStack.bottomAnchor constraintLessThanOrEqualToAnchor:container.bottomAnchor constant:-16]
]];
]];
//
Unit label
//
Move labels into stack
self.unitLabel = [[UILabel alloc] init];
self.unitLabel = [[UILabel alloc] init];
self.unitLabel.text = @"For Unit No.:";
self.unitLabel.text = @"For Unit No.:";
self.unitLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightThin];
self.unitLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightThin];
self.unitLabel.textColor = [UIColor grayColor];
self.unitLabel.textColor = [UIColor grayColor];
self.unitLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.unitLabel];
self.unitLabelName = [[UILabel alloc] init];
self.unitLabelName = [[UILabel alloc] init];
self.unitLabelName.text = [NSString stringWithFormat:@"%@, %@", self.projectName, self.projectId];
self.unitLabelName.text = [NSString stringWithFormat:@"%@, %@", self.projectName, self.projectId];
self.unitLabelName.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
self.unitLabelName.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
self.unitLabelName.textColor = [UIColor blackColor];
self.unitLabelName.textColor = [UIColor blackColor];
self.unitLabelName.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.unitLabelName];
self.stepLabel = [[UILabel alloc] init];
self.stepLabel = [[UILabel alloc] init];
self.stepLabel.text = @"Step 2/3: Select your preferred time";
self.stepLabel.text = @"Step 2/3: Select your preferred time";
self.stepLabel.font = [UIFont systemFontOfSize:14];
self.stepLabel.font = [UIFont systemFontOfSize:14];
self.stepLabel.textColor = [UIColor blackColor];
self.stepLabel.textColor = [UIColor blackColor];
self.stepLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.stepLabel.textAlignment = NSTextAlignmentCenter;
self.stepLabel.textAlignment = NSTextAlignmentCenter;
self.stepLabel.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
self.stepLabel.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
self.stepLabel.layer.cornerRadius = 6.0;
self.stepLabel.layer.cornerRadius = 6.0;
self.stepLabel.clipsToBounds = YES;
self.stepLabel.clipsToBounds = YES;
[self.view addSubview:self.stepLabel];
[[self.stepLabel.heightAnchor constraintEqualToConstant:30] setActive:YES];
[NSLayoutConstraint activateConstraints:@[
// Section header for time slots
[self.unitLabel.topAnchor constraintEqualToAnchor:self.headerBar.bottomAnchor constant:16],
UILabel *timeSlotHeader = [[UILabel alloc] init];
[self.unitLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
timeSlotHeader.text = @"Available Time Slots";
[self.unitLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
timeSlotHeader.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
timeSlotHeader.textColor = [UIColor darkGrayColor];
[self.unitLabelName.topAnchor constraintEqualToAnchor:self.unitLabel.bottomAnchor constant:8],
timeSlotHeader.textAlignment = NSTextAlignmentLeft;
[self.unitLabelName.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[self.unitLabelName.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
[self.contentStack addArrangedSubview:self.unitLabel];
[self.contentStack addArrangedSubview:self.unitLabelName];
[self.stepLabel.topAnchor constraintEqualToAnchor:self.unitLabelName.bottomAnchor constant:16],
[self.contentStack addArrangedSubview:self.stepLabel];
[self.stepLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
[self.contentStack addArrangedSubview:timeSlotHeader];
[self.stepLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
[self.stepLabel.heightAnchor constraintEqualToConstant:30]
]];
}
}
- (void)setupFooter {
- (void)setupFooter {
...
@@ -283,92 +276,55 @@
...
@@ -283,92 +276,55 @@
}
}
#pragma mark - Time Slot UI (2-column grid)
#pragma mark - Time Slot UI (2-column grid)
- (void)rebuildTimeSlotViews {
- (void)rebuildTimeSlotViews {
// First remove any previously added time-slot views from contentStack (after the step container)
// Remove previous time slot views (keep first 4: unitLabel, unitLabelName, stepLabel, header)
// Find index of step container in contentStack then remove everything after it, or simply remove any arranged subviews that are not the first 3
while (self.contentStack.arrangedSubviews.count > 4) {
// We'll remove any arranged subviews after the step container to keep labels intact.
while (self.contentStack.arrangedSubviews.count > 3) {
UIView *v = self.contentStack.arrangedSubviews.lastObject;
UIView *v = self.contentStack.arrangedSubviews.lastObject;
[self.contentStack removeArrangedSubview:v];
[self.contentStack removeArrangedSubview:v];
[v removeFromSuperview];
[v removeFromSuperview];
}
}
// Create container for time slots
UIView *slotsContainer = [[UIView alloc] init];
slotsContainer.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentStack addArrangedSubview:slotsContainer];
// Build rows: two items per row
// Build rows: two items per row
NSInteger count = self.aryTimeSlot.count;
NSInteger count = self.aryTimeSlot.count;
for (NSInteger i = 0; i < count; i += 2) {
for (NSInteger i = 0; i < count; i += 2) {
UIView *row = [[UIView alloc] init];
UIView *row = [[UIView alloc] init];
row.translatesAutoresizingMaskIntoConstraints = NO;
row.translatesAutoresizingMaskIntoConstraints = NO;
row.backgroundColor = UIColor.clearColor;
row.backgroundColor = UIColor.clearColor;
[[row.heightAnchor constraintEqualToConstant:40] setActive:YES];
// Left slot
// Left slot
NSDictionary *left = self.aryTimeSlot[i];
NSDictionary *left = self.aryTimeSlot[i];
UIButton *leftBtn = [self createTimeSlotButtonForIndex:i slot:left];
UIButton *leftBtn = [self createTimeSlotButtonForIndex:i slot:left];
leftBtn.translatesAutoresizingMaskIntoConstraints = NO;
[row addSubview:leftBtn];
[row addSubview:leftBtn];
// Right slot (may not exist)
UIButton *rightBtn = nil;
if (i + 1 < count) {
NSDictionary *right = self.aryTimeSlot[i+1];
rightBtn = [self createTimeSlotButtonForIndex:i+1 slot:right];
rightBtn.translatesAutoresizingMaskIntoConstraints = NO;
[row addSubview:rightBtn];
}
[slotsContainer addSubview:row];
// Layout row children
CGFloat padding = 0;
[NSLayoutConstraint activateConstraints:@[
[row.leadingAnchor constraintEqualToAnchor:slotsContainer.leadingAnchor],
[row.trailingAnchor constraintEqualToAnchor:slotsContainer.trailingAnchor],
// height fixed same as RN (40)
[row.heightAnchor constraintEqualToConstant:40],
]];
[NSLayoutConstraint activateConstraints:@[
[NSLayoutConstraint activateConstraints:@[
[leftBtn.leadingAnchor constraintEqualToAnchor:row.leadingAnchor
constant:0
],
[leftBtn.leadingAnchor constraintEqualToAnchor:row.leadingAnchor],
[leftBtn.topAnchor constraintEqualToAnchor:row.topAnchor
constant:0
],
[leftBtn.topAnchor constraintEqualToAnchor:row.topAnchor],
[leftBtn.bottomAnchor constraintEqualToAnchor:row.bottomAnchor
constant:0
],
[leftBtn.bottomAnchor constraintEqualToAnchor:row.bottomAnchor],
[leftBtn.widthAnchor constraintEqualToAnchor:row.widthAnchor multiplier:0.5 constant:-10]
[leftBtn.widthAnchor constraintEqualToAnchor:row.widthAnchor multiplier:0.5 constant:-10]
]];
]];
if (rightBtn) {
// Right slot
if (i + 1 < count) {
NSDictionary *right = self.aryTimeSlot[i+1];
UIButton *rightBtn = [self createTimeSlotButtonForIndex:i+1 slot:right];
[row addSubview:rightBtn];
[NSLayoutConstraint activateConstraints:@[
[NSLayoutConstraint activateConstraints:@[
[rightBtn.trailingAnchor constraintEqualToAnchor:row.trailingAnchor constant:0],
[rightBtn.topAnchor constraintEqualToAnchor:row.topAnchor constant:0],
[rightBtn.bottomAnchor constraintEqualToAnchor:row.bottomAnchor constant:0],
[rightBtn.leadingAnchor constraintEqualToAnchor:leftBtn.trailingAnchor constant:20],
[rightBtn.leadingAnchor constraintEqualToAnchor:leftBtn.trailingAnchor constant:20],
[rightBtn.trailingAnchor constraintEqualToAnchor:row.trailingAnchor],
[rightBtn.topAnchor constraintEqualToAnchor:row.topAnchor],
[rightBtn.bottomAnchor constraintEqualToAnchor:row.bottomAnchor],
[rightBtn.widthAnchor constraintEqualToAnchor:leftBtn.widthAnchor]
[rightBtn.widthAnchor constraintEqualToAnchor:leftBtn.widthAnchor]
]];
]];
} else {
// if right missing, fill space with empty view to keep alignment
UIView *filler = [[UIView alloc] init];
filler.translatesAutoresizingMaskIntoConstraints = NO;
[row addSubview:filler];
[NSLayoutConstraint activateConstraints:@[
[filler.leadingAnchor constraintEqualToAnchor:leftBtn.trailingAnchor constant:20],
[filler.trailingAnchor constraintEqualToAnchor:row.trailingAnchor constant:0],
[filler.topAnchor constraintEqualToAnchor:row.topAnchor constant:0],
[filler.bottomAnchor constraintEqualToAnchor:row.bottomAnchor constant:0]
]];
}
}
// Add spacing below each row
[self.contentStack addArrangedSubview:row];
// Spacer between rows
UIView *spacer = [[UIView alloc] init];
UIView *spacer = [[UIView alloc] init];
spacer.translatesAutoresizingMaskIntoConstraints = NO;
spacer.translatesAutoresizingMaskIntoConstraints = NO;
spacer.backgroundColor = UIColor.clearColor;
[spacer.heightAnchor constraintEqualToConstant:8].active = YES;
[self.contentStack addArrangedSubview:row];
[self.contentStack addArrangedSubview:spacer];
[self.contentStack addArrangedSubview:spacer];
[NSLayoutConstraint activateConstraints:@[
[spacer.heightAnchor constraintEqualToConstant:8]
]];
}
}
}
}
...
@@ -421,8 +377,13 @@
...
@@ -421,8 +377,13 @@
}
}
- (void)nextTapped:(id)sender {
- (void)nextTapped:(id)sender {
if (self.selectedSlotID.length == 0 || self.selectedStartDate.length == 0 || self.selectedStartTime.length == 0) {
if (self.selectedSlotID.length == 0 ||
UIAlertController *a = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Please select a time slot to continue." preferredStyle:UIAlertControllerStyleAlert];
self.selectedStartDate.length == 0 ||
self.selectedStartTime.length == 0) {
UIAlertController *a = [UIAlertController alertControllerWithTitle:@"Alert"
message:@"Please select a time slot to continue."
preferredStyle:UIAlertControllerStyleAlert];
[a addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[a addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:a animated:YES completion:nil];
[self presentViewController:a animated:YES completion:nil];
return;
return;
...
@@ -435,21 +396,16 @@
...
@@ -435,21 +396,16 @@
if (self.didSelectAppointment) {
if (self.didSelectAppointment) {
self.didSelectAppointment([obj copy]);
self.didSelectAppointment([obj copy]);
} else {
return;
// push AppointmentConfirmationViewController (assumes it exists)
// You must replace the below lines with your app's confirmation screen push
UIViewController *conf = [NSClassFromString(@"AppointmentConfirmationViewController") new];
if (conf) {
if ([conf respondsToSelector:@selector(setAppointmentInfo:)]) {
// prefer setter if exists
[conf setValue:[obj copy] forKey:@"appointmentInfo"];
}
[self.navigationController pushViewController:conf animated:YES];
} else {
// fallback: just log
NSLog(@"Next tapped - appointment object: %@", obj);
}
}
}
AppointmentConfirmationViewController *appointVC = [[AppointmentConfirmationViewController alloc] init];
appointVC.slotId = self.selectedSlotID;
appointVC.startDate = self.selectedStartDate;
appointVC.startTime = self.selectedStartTime;
appointVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:appointVC animated:YES completion:nil];
}
}
- (void)timeSlotTapped:(UIButton *)sender {
- (void)timeSlotTapped:(UIButton *)sender {
...
...
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentViewController.h
View file @
09397ebc
...
@@ -9,8 +9,8 @@ NS_ASSUME_NONNULL_BEGIN
...
@@ -9,8 +9,8 @@ NS_ASSUME_NONNULL_BEGIN
@property
(
nonatomic
,
strong
)
NSString
*
projectName
;
@property
(
nonatomic
,
strong
)
NSString
*
projectName
;
@property
(
nonatomic
,
strong
)
NSString
*
projectId
;
@property
(
nonatomic
,
strong
)
NSString
*
projectId
;
@property
(
nonatomic
,
strong
)
NSArray
*
allSlots
;
// Equivalent to rawSlots
@property
(
nonatomic
,
strong
)
NSArray
*
allSlots
;
@property
(
nonatomic
,
strong
)
NSMutableArray
*
aryTimeSlot
;
// Equivalent to aryTimeSlotTemp
@property
(
nonatomic
,
strong
)
NSMutableArray
*
aryTimeSlot
;
@property
(
nonatomic
,
strong
)
NSString
*
selectedDateString
;
@property
(
nonatomic
,
strong
)
NSString
*
selectedDateString
;
@property
(
nonatomic
,
strong
)
NSDictionary
*
markedDates
;
@property
(
nonatomic
,
strong
)
NSDictionary
*
markedDates
;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentViewMoreViewController.h
0 → 100644
View file @
09397ebc
// AppointmentViewMoreViewController.h
#import <UIKit/UIKit.h>
@interface
AppointmentViewMoreViewController
:
UIViewController
@end
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentViewMoreViewController.mm
0 → 100644
View file @
09397ebc
// AppointmentViewMoreViewController.mm
#import "AppointmentViewMoreViewController.h"
@interface AppointmentViewMoreViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UIView *topBar;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *toggleTabButton;
@property (nonatomic, strong) UIView *filterBar;
@property (nonatomic, strong) UILabel *filterLabel;
@property (nonatomic, strong) UIButton *filterButton;
@property (nonatomic, strong) UIView *calendarContainer;
@property (nonatomic, strong) UIView *listingContainer;
@property (nonatomic, strong) UITableView *listingTable;
@property (nonatomic, strong) UIView *bottomButtonContainer;
@property (nonatomic, strong) UIButton *makeAppointmentButton;
@property (nonatomic, strong) UIView *filterOverlay;
@property (nonatomic, strong) UIActivityIndicatorView *loadingView;
@property (nonatomic, assign) BOOL showingCalendar;
@end
@implementation AppointmentViewMoreViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.showingCalendar = YES;
[self setupTopBar];
[self setupFilterBar];
[self setupCalendarView];
[self setupListingView];
[self setupBottomButton];
[self setupFilterOverlay];
[self setupLoadingOverlay];
}
#pragma mark - Top Bar
- (void)setupTopBar {
self.topBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 48)];
self.topBar.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0.55 alpha:1];
[self.view addSubview:self.topBar];
self.backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 48, 48)];
[self.backButton setImage:[UIImage imageNamed:@"back24"] forState:UIControlStateNormal];
[self.backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
[self.topBar addSubview:self.backButton];
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(48, 0,
self.view.bounds.size.width - 96, 48)];
self.titleLabel.text = @"Appointment";
self.titleLabel.textColor = UIColor.whiteColor;
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.topBar addSubview:self.titleLabel];
self.toggleTabButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.bounds.size.width - 48, 0, 48, 48)];
[self.toggleTabButton setImage:[UIImage imageNamed:@"listing_icon_white"] forState:UIControlStateNormal];
[self.toggleTabButton addTarget:self action:@selector(onToggleTab) forControlEvents:UIControlEventTouchUpInside];
[self.topBar addSubview:self.toggleTabButton];
}
#pragma mark - Filter Bar
- (void)setupFilterBar {
self.filterBar = [[UIView alloc] initWithFrame:CGRectMake(0, 48, self.view.bounds.size.width, 48)];
self.filterBar.backgroundColor = [UIColor colorWithWhite:0.6 alpha:1];
[self.view addSubview:self.filterBar];
self.filterLabel = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, self.view.bounds.size.width - 64, 48)];
self.filterLabel.text = @"Filter by All (Upcoming)";
self.filterLabel.textColor = UIColor.whiteColor;
[self.filterBar addSubview:self.filterLabel];
self.filterButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.bounds.size.width - 48, 0, 48, 48)];
[self.filterButton setImage:[UIImage imageNamed:@"filter_icon"] forState:UIControlStateNormal];
[self.filterButton addTarget:self action:@selector(onFilterButton) forControlEvents:UIControlEventTouchUpInside];
[self.filterBar addSubview:self.filterButton];
}
#pragma mark - Calendar (placeholder container)
- (void)setupCalendarView {
CGFloat top = CGRectGetMaxY(self.filterBar.frame);
self.calendarContainer = [[UIView alloc] initWithFrame:CGRectMake(0, top,
self.view.bounds.size.width,
self.view.bounds.size.height - top - 62)];
self.calendarContainer.backgroundColor = UIColor.whiteColor;
UILabel *placeholder = [[UILabel alloc] initWithFrame:self.calendarContainer.bounds];
placeholder.text = @"CALENDAR VIEW PLACEHOLDER";
placeholder.textAlignment = NSTextAlignmentCenter;
placeholder.textColor = UIColor.darkGrayColor;
[self.calendarContainer addSubview:placeholder];
[self.view addSubview:self.calendarContainer];
}
#pragma mark - Listing Table
- (void)setupListingView {
CGFloat top = CGRectGetMaxY(self.filterBar.frame);
self.listingContainer = [[UIView alloc] initWithFrame:CGRectMake(0, top,
self.view.bounds.size.width,
self.view.bounds.size.height - top - 62)];
self.listingContainer.backgroundColor = UIColor.whiteColor;
self.listingContainer.hidden = YES;
self.listingTable = [[UITableView alloc] initWithFrame:self.listingContainer.bounds style:UITableViewStyleGrouped];
self.listingTable.delegate = self;
self.listingTable.dataSource = self;
[self.listingContainer addSubview:self.listingTable];
[self.view addSubview:self.listingContainer];
}
#pragma mark - Bottom Button
- (void)setupBottomButton {
CGFloat h = 62;
self.bottomButtonContainer = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height - h, self.view.bounds.size.width, h)];
self.bottomButtonContainer.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0.55 alpha:1];
[self.view addSubview:self.bottomButtonContainer];
self.makeAppointmentButton = [[UIButton alloc] initWithFrame:self.bottomButtonContainer.bounds];
[self.makeAppointmentButton setTitle:@"Make Appointment" forState:UIControlStateNormal];
[self.makeAppointmentButton addTarget:self action:@selector(onMakeAppointment) forControlEvents:UIControlEventTouchUpInside];
[self.bottomButtonContainer addSubview:self.makeAppointmentButton];
}
#pragma mark - Filter Overlay
- (void)setupFilterOverlay {
self.filterOverlay = [[UIView alloc] initWithFrame:self.view.bounds];
self.filterOverlay.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7];
self.filterOverlay.hidden = YES;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, self.view.bounds.size.width, 40)];
label.text = @"FILTER OPTIONS PLACEHOLDER";
label.textAlignment = NSTextAlignmentCenter;
[self.filterOverlay addSubview:label];
[self.view addSubview:self.filterOverlay];
}
#pragma mark - Loading Overlay
- (void)setupLoadingOverlay {
self.loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
self.loadingView.center = self.view.center;
self.loadingView.hidesWhenStopped = YES;
[self.view addSubview:self.loadingView];
}
#pragma mark - Actions
- (void)onBack {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)onToggleTab {
self.showingCalendar = !self.showingCalendar;
self.calendarContainer.hidden = !self.showingCalendar;
self.listingContainer.hidden = self.showingCalendar;
}
- (void)onFilterButton {
self.filterOverlay.hidden = !self.filterOverlay.hidden;
}
- (void)onMakeAppointment {
NSLog(@"Make appointment tapped");
}
#pragma mark - TableView placeholder methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3; // placeholder
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2; // placeholder
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = @"listingCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (!cell) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
cell.textLabel.text = @"Unit No";
cell.detailTextLabel.text = @"Owner Name";
return cell;
}
@end
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/DashboardViewController.mm
View file @
09397ebc
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#import "IssueDetailViewController.h"
#import "IssueDetailViewController.h"
#import "IssuesViewController.h"
#import "IssuesViewController.h"
#import "AppointmentViewController.h"
#import "AppointmentViewController.h"
#import "AppointmentDetailsViewController.h"
@interface DashboardViewController ()
@interface DashboardViewController ()
...
@@ -691,7 +692,6 @@
...
@@ -691,7 +692,6 @@
return card;
return card;
}
}
- (UIView *)makeAppointmentCard:(NSDictionary *)item width:(CGFloat)width {
- (UIView *)makeAppointmentCard:(NSDictionary *)item width:(CGFloat)width {
UIView *card = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 90)];
UIView *card = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 90)];
card.backgroundColor = UIColor.whiteColor;
card.backgroundColor = UIColor.whiteColor;
...
@@ -717,7 +717,7 @@
...
@@ -717,7 +717,7 @@
// Notification Icon
// Notification Icon
UIView *iconCircle = [[UIView alloc] initWithFrame:CGRectMake(12, 14, 24, 24)];
UIView *iconCircle = [[UIView alloc] initWithFrame:CGRectMake(12, 14, 24, 24)];
iconCircle.backgroundColor = [UIColor colorWithRed:1.0 green:0.4 blue:0.4 alpha:1.0];
// red tone
iconCircle.backgroundColor = [UIColor colorWithRed:1.0 green:0.4 blue:0.4 alpha:1.0];
iconCircle.layer.cornerRadius = 12;
iconCircle.layer.cornerRadius = 12;
UIImageView *bell = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"bell.fill"]];
UIImageView *bell = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"bell.fill"]];
...
@@ -726,14 +726,14 @@
...
@@ -726,14 +726,14 @@
[iconCircle addSubview:bell];
[iconCircle addSubview:bell];
[card addSubview:iconCircle];
[card addSubview:iconCircle];
//
=== Status ===
//
Status
UILabel *statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(44, 12, 180, 26)];
UILabel *statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(44, 12, 180, 26)];
statusLabel.text = status;
statusLabel.text = status;
statusLabel.font = [UIFont boldSystemFontOfSize:17];
statusLabel.font = [UIFont boldSystemFontOfSize:17];
statusLabel.textColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0];
// teal
statusLabel.textColor = [UIColor colorWithRed:0.0 green:0.43 blue:0.55 alpha:1.0];
[card addSubview:statusLabel];
[card addSubview:statusLabel];
//
=== Time (right aligned) ===
//
Time
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(width - 90, 12, 80, 26)];
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(width - 90, 12, 80, 26)];
timeLabel.textAlignment = NSTextAlignmentRight;
timeLabel.textAlignment = NSTextAlignmentRight;
timeLabel.text = startTime;
timeLabel.text = startTime;
...
@@ -741,10 +741,8 @@
...
@@ -741,10 +741,8 @@
timeLabel.textColor = [UIColor grayColor];
timeLabel.textColor = [UIColor grayColor];
[card addSubview:timeLabel];
[card addSubview:timeLabel];
// === Description text ===
// Description
NSString *desc = [NSString stringWithFormat:
NSString *desc = [NSString stringWithFormat:@"You have a %@ appointment on %@, %@", appointmentType, startDate, buyerName];
@"You have a %@ appointment on %@, %@",
appointmentType, startDate, buyerName];
UILabel *descLabel = [[UILabel alloc] initWithFrame:CGRectMake(16, 46, width - 32, 36)];
UILabel *descLabel = [[UILabel alloc] initWithFrame:CGRectMake(16, 46, width - 32, 36)];
descLabel.text = desc;
descLabel.text = desc;
...
@@ -753,7 +751,10 @@
...
@@ -753,7 +751,10 @@
descLabel.textColor = [UIColor blackColor];
descLabel.textColor = [UIColor blackColor];
[card addSubview:descLabel];
[card addSubview:descLabel];
// === Tap animation ===
// Store appointment data so tap handler can retrieve it
objc_setAssociatedObject(card, "appointmentData", item, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// Tap
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleAppointmentTap:)];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleAppointmentTap:)];
[card addGestureRecognizer:tap];
[card addGestureRecognizer:tap];
...
@@ -971,8 +972,22 @@
...
@@ -971,8 +972,22 @@
- (void)handleAppointmentTap:(UITapGestureRecognizer *)gesture {
- (void)handleAppointmentTap:(UITapGestureRecognizer *)gesture {
UIView *card = gesture.view;
UIView *card = gesture.view;
[self animateTapForView:card];
[self animateTapForView:card];
NSLog(@"📅 Appointment card tapped");
// TODO: open AppointmentDetails in future
NSDictionary *appointmentData = objc_getAssociatedObject(card, "appointmentData");
if (!appointmentData) {
NSLog(@"⚠️ No appointment data found");
return;
}
NSLog(@"📅 Opening AppointmentDetails with: %@", appointmentData);
AppointmentDetailsViewController *vc = [[AppointmentDetailsViewController alloc] init];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
//vc.something = something;
[self presentViewController:vc animated:YES completion:nil];
}
}
- (void)handleIssueTap:(UITapGestureRecognizer *)gesture {
- (void)handleIssueTap:(UITapGestureRecognizer *)gesture {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment