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
82cef0dc
Commit
82cef0dc
authored
Jan 09, 2026
by
Wei Han
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
code update
parent
4a7abd98
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
218 additions
and
108 deletions
+218
-108
project.pbxproj
...ginFramework/QmsPluginFramework.xcodeproj/project.pbxproj
+4
-0
AccessAppointmentViewController.mm
...inFramework/AccessItem/AccessAppointmentViewController.mm
+1
-1
AppointmentDetailsViewController.mm
...Framework/Appointment/AppointmentDetailsViewController.mm
+2
-2
AppointmentViewController.mm
...sPluginFramework/Appointment/AppointmentViewController.mm
+56
-42
AppointmentViewMoreViewController.mm
...ramework/Appointment/AppointmentViewMoreViewController.mm
+1
-1
DashboardViewController.h
...rk/QmsPluginFramework/Dashboard/DashboardViewController.h
+1
-0
DashboardViewController.mm
...k/QmsPluginFramework/Dashboard/DashboardViewController.mm
+0
-0
GeneralInfoViewController.mm
...QmsPluginFramework/Dashboard/GeneralInfoViewController.mm
+1
-1
ProjectViewController.mm
...ork/QmsPluginFramework/Dashboard/ProjectViewController.mm
+41
-25
UnitViewController.h
...amework/QmsPluginFramework/Dashboard/UnitViewController.h
+1
-0
UnitViewController.mm
...mework/QmsPluginFramework/Dashboard/UnitViewController.mm
+2
-1
AddInfoViewController.mm
...amework/QmsPluginFramework/Issue/AddInfoViewController.mm
+2
-2
DetailsViewController.mm
...msPluginFramework/Issue/AddIssue/DetailsViewController.mm
+2
-2
PlanViewController.mm
...k/QmsPluginFramework/Issue/AddIssue/PlanViewController.mm
+2
-2
HistoryViewController.mm
...amework/QmsPluginFramework/Issue/HistoryViewController.mm
+1
-1
IssuesViewController.mm
...ramework/QmsPluginFramework/Issue/IssuesViewController.mm
+1
-1
WithdrawIssuesViewController.mm
.../QmsPluginFramework/Issue/WithdrawIssuesViewController.mm
+2
-2
WithdrawSingleIssueViewController.mm
...luginFramework/Issue/WithdrawSingleIssueViewController.mm
+2
-2
SyncProjectViewController.mm
...work/QmsPluginFramework/Sync/SyncProjectViewController.mm
+2
-1
APIClient.h
...ginFramework/QmsPluginFramework/Utilities/API/APIClient.h
+22
-22
APIClient.mm
...inFramework/QmsPluginFramework/Utilities/API/APIClient.mm
+0
-0
APIConfig.h
...ginFramework/QmsPluginFramework/Utilities/API/APIConfig.h
+7
-0
APIConfig.mm
...inFramework/QmsPluginFramework/Utilities/API/APIConfig.mm
+65
-0
OfflineSyncManager.mm
...uginFramework/Utilities/OfflineSync/OfflineSyncManager.mm
+0
-0
No files found.
framework/QmsPluginFramework/QmsPluginFramework.xcodeproj/project.pbxproj
View file @
82cef0dc
...
@@ -239,6 +239,7 @@
...
@@ -239,6 +239,7 @@
TargetAttributes
=
{
TargetAttributes
=
{
2F9647642E86307D002CC7CB
=
{
2F9647642E86307D002CC7CB
=
{
CreatedOnToolsVersion
=
26.0.1
;
CreatedOnToolsVersion
=
26.0.1
;
LastSwiftMigration
=
2620
;
};
};
2FC779A82F0E1C310002A1D4
=
{
2FC779A82F0E1C310002A1D4
=
{
CreatedOnToolsVersion
=
26.2
;
CreatedOnToolsVersion
=
26.2
;
...
@@ -312,6 +313,7 @@
...
@@ -312,6 +313,7 @@
isa
=
XCBuildConfiguration
;
isa
=
XCBuildConfiguration
;
buildSettings
=
{
buildSettings
=
{
BUILD_LIBRARY_FOR_DISTRIBUTION
=
YES
;
BUILD_LIBRARY_FOR_DISTRIBUTION
=
YES
;
CLANG_ENABLE_MODULES
=
YES
;
CODE_SIGN_STYLE
=
Automatic
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
1
;
CURRENT_PROJECT_VERSION
=
1
;
DEFINES_MODULE
=
YES
;
DEFINES_MODULE
=
YES
;
...
@@ -343,6 +345,7 @@
...
@@ -343,6 +345,7 @@
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD
=
NO
;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD
=
NO
;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD
=
NO
;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD
=
NO
;
SWIFT_EMIT_LOC_STRINGS
=
YES
;
SWIFT_EMIT_LOC_STRINGS
=
YES
;
SWIFT_OPTIMIZATION_LEVEL
=
"-Onone"
;
SWIFT_VERSION
=
4.0
;
SWIFT_VERSION
=
4.0
;
TARGETED_DEVICE_FAMILY
=
"1,2"
;
TARGETED_DEVICE_FAMILY
=
"1,2"
;
};
};
...
@@ -352,6 +355,7 @@
...
@@ -352,6 +355,7 @@
isa
=
XCBuildConfiguration
;
isa
=
XCBuildConfiguration
;
buildSettings
=
{
buildSettings
=
{
BUILD_LIBRARY_FOR_DISTRIBUTION
=
YES
;
BUILD_LIBRARY_FOR_DISTRIBUTION
=
YES
;
CLANG_ENABLE_MODULES
=
YES
;
CODE_SIGN_STYLE
=
Automatic
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
1
;
CURRENT_PROJECT_VERSION
=
1
;
DEFINES_MODULE
=
YES
;
DEFINES_MODULE
=
YES
;
...
...
framework/QmsPluginFramework/QmsPluginFramework/AccessItem/AccessAppointmentViewController.mm
View file @
82cef0dc
...
@@ -514,7 +514,7 @@
...
@@ -514,7 +514,7 @@
[APIClient requestCancelAppointment:self.appointmentData[@"appointment_id"]
[APIClient requestCancelAppointment:self.appointmentData[@"appointment_id"]
reason:remarks
reason:remarks
completion:^(NSDictionary *data, NSError *error)
completion:^(
BOOL success,
NSDictionary *data, NSError *error)
{
{
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
...
...
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentDetailsViewController.mm
View file @
82cef0dc
...
@@ -933,7 +933,7 @@
...
@@ -933,7 +933,7 @@
[
APIClient
requestCancelAppointment:self
.
appointmentData
[@"
id
"]
[
APIClient
requestCancelAppointment:self
.
appointmentData
[@"
id
"]
reason:remarks
reason:remarks
completion:
^(
NSDictionary
*
data
,
NSError
*
error
)
completion:
^(
BOOL
success
,
NSDictionary
*
data
,
NSError
*
error
)
{
{
dispatch_async
(
dispatch_get_main_queue
(),
^{
dispatch_async
(
dispatch_get_main_queue
(),
^{
...
@@ -966,7 +966,7 @@
...
@@ -966,7 +966,7 @@
}
}
-
(
void
)
requestGeneralInfo
{
-
(
void
)
requestGeneralInfo
{
[
APIClient
requestGeneralInfo:
^(
NSDictionary
*
data
,
NSError
*
error
)
{
[
APIClient
requestGeneralInfo:
^(
BOOL
success
,
NSDictionary
*
data
,
NSError
*
error
)
{
if
(
error
)
return
;
if
(
error
)
return
;
NSDictionary
*
generalInfo =
data[@"Data"];
NSDictionary
*
generalInfo =
data[@"Data"];
self
.
floorPlanImage =
generalInfo[@"image"];
self
.
floorPlanImage =
generalInfo[@"image"];
...
...
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentViewController.mm
View file @
82cef0dc
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
@property (nonatomic, strong) WKWebView *termsWebView;
@property (nonatomic, strong) WKWebView *termsWebView;
@property (nonatomic, strong) NSString *termsAndCondition;
@property (nonatomic, strong) NSString *termsAndCondition;
@property (nonatomic, strong) NSString *appointmentType;
@property (nonatomic, strong) NSString *appointmentType;
@property (nonatomic, assign) BOOL hasLoadedTermsHTML;
// Labels
// Labels
@property (nonatomic, strong) UILabel *unitLabel;
@property (nonatomic, strong) UILabel *unitLabel;
...
@@ -61,12 +62,23 @@
...
@@ -61,12 +62,23 @@
- (void)viewDidLoad {
- (void)viewDidLoad {
[super viewDidLoad];
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
self.view.backgroundColor = UIColor.whiteColor;
[self requestAppointment];
[self requestGeneralInfo];
[self setupHeader];
[self setupHeader];
[self setupFooter];
[self setupFooter];
[self setupUI];
[self setupUI];
}
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (self.termsAndCondition
&&
!self.hasLoadedTermsHTML) {
[self.termsWebView loadHTMLString:self.termsAndCondition baseURL:nil];
self.hasLoadedTermsHTML = YES;
}
}
#pragma mark - Setup UI
#pragma mark - Setup UI
- (void)setupUI {
- (void)setupUI {
// Scroll view
// Scroll view
...
@@ -173,41 +185,43 @@
...
@@ -173,41 +185,43 @@
#pragma mark = Overlay t
&
c
#pragma mark = Overlay t
&
c
- (void)setupTermsOverlay {
- (void)setupTermsOverlay {
// Overlay background
self.termsOverlay = [[UIView alloc] init];
self.termsOverlay = [[UIView alloc] init];
self.termsOverlay.backgroundColor = UIColor.whiteColor;
self.termsOverlay.backgroundColor = UIColor.whiteColor;
self.termsOverlay.translatesAutoresizingMaskIntoConstraints = NO;
self.termsOverlay.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.termsOverlay];
[self.view addSubview:self.termsOverlay];
UILayoutGuide *safe = self.view.safeAreaLayoutGuide;
[NSLayoutConstraint activateConstraints:@[
[NSLayoutConstraint activateConstraints:@[
[self.termsOverlay.topAnchor constraintEqualToAnchor:self.headerBar.bottomAnchor],
[self.termsOverlay.topAnchor constraintEqualToAnchor:self.headerBar.bottomAnchor],
[self.termsOverlay.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.termsOverlay.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.termsOverlay.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.termsOverlay.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.termsOverlay.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
,
[self.termsOverlay.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
]];
]];
// Title
self.termsTitleLabel = [[UILabel alloc] init];
self.termsTitleLabel = [[UILabel alloc] init];
self.termsTitleLabel.text = @"Terms
&
Conditions";
self.termsTitleLabel.text = @"Terms
&
Conditions";
self.termsTitleLabel.font = [UIFont boldSystemFontOfSize:18];
self.termsTitleLabel.font = [UIFont boldSystemFontOfSize:18];
self.termsTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.termsTitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.termsOverlay addSubview:self.termsTitleLabel];
[self.termsOverlay addSubview:self.termsTitleLabel];
// WebView container
self.termsContainer = [[UIView alloc] init];
self.termsContainer = [[UIView alloc] init];
self.termsContainer.backgroundColor = [UIColor c
olorWithWhite:0.95 alpha:1.0
];
self.termsContainer.backgroundColor = [UIColor c
learColor
];
self.termsContainer.layer.cornerRadius = 12.0;
self.termsContainer.layer.cornerRadius = 12.0;
self.termsContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.termsContainer.translatesAutoresizingMaskIntoConstraints = NO;
[self.termsOverlay addSubview:self.termsContainer];
[self.termsOverlay addSubview:self.termsContainer];
// WKWebView
// WKWebView
self.termsWebView = [[WKWebView alloc] initWithFrame:CGRectZero];
self.termsWebView = [[WKWebView alloc] initWithFrame:CGRectZero];
self.termsWebView.translatesAutoresizingMaskIntoConstraints = NO;
self.termsWebView.translatesAutoresizingMaskIntoConstraints = NO;
self.termsWebView.scrollView.delegate = self;
self.termsWebView.scrollView.delegate = self;
self.termsWebView.navigationDelegate = self;
self.termsWebView.navigationDelegate = self;
self.termsWebView.opaque = NO;
self.termsWebView.backgroundColor = [UIColor clearColor];
[self.termsContainer addSubview:self.termsWebView];
[self.termsContainer addSubview:self.termsWebView];
self.termsContainer.backgroundColor = [UIColor yellowColor];
self.termsWebView.backgroundColor = [UIColor redColor];
// Agree button
// Agree button
self.agreeButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.agreeButton = [UIButton buttonWithType:UIButtonTypeSystem];
self.agreeButton.translatesAutoresizingMaskIntoConstraints = NO;
self.agreeButton.translatesAutoresizingMaskIntoConstraints = NO;
...
@@ -219,23 +233,23 @@
...
@@ -219,23 +233,23 @@
[self.agreeButton addTarget:self action:@selector(handleAgreeTapped)
[self.agreeButton addTarget:self action:@selector(handleAgreeTapped)
forControlEvents:UIControlEventTouchUpInside];
forControlEvents:UIControlEventTouchUpInside];
[self.termsOverlay addSubview:self.agreeButton];
[self.termsOverlay addSubview:self.agreeButton];
// Layout
// Layout
constraints
[NSLayoutConstraint activateConstraints:@[
[NSLayoutConstraint activateConstraints:@[
[self.termsTitleLabel.topAnchor constraintEqualToAnchor:self.termsOverlay.topAnchor constant:40],
[self.termsTitleLabel.topAnchor constraintEqualToAnchor:self.termsOverlay.topAnchor constant:40],
[self.termsTitleLabel.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:20],
[self.termsTitleLabel.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:20],
[self.termsTitleLabel.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-20],
[self.termsTitleLabel.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-20],
[self.termsContainer.topAnchor constraintEqualToAnchor:self.termsTitleLabel.bottomAnchor constant:12],
[self.termsContainer.topAnchor constraintEqualToAnchor:self.termsTitleLabel.bottomAnchor constant:12],
[self.termsContainer.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:20],
[self.termsContainer.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:20],
[self.termsContainer.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-20],
[self.termsContainer.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-20],
[self.termsContainer.bottomAnchor constraintEqualToAnchor:self.agreeButton.topAnchor constant:-20],
[self.termsContainer.bottomAnchor constraintEqualToAnchor:self.agreeButton.topAnchor constant:-20],
[self.termsWebView.topAnchor constraintEqualToAnchor:self.termsContainer.topAnchor],
[self.termsWebView.topAnchor constraintEqualToAnchor:self.termsContainer.topAnchor],
[self.termsWebView.leadingAnchor constraintEqualToAnchor:self.termsContainer.leadingAnchor],
[self.termsWebView.leadingAnchor constraintEqualToAnchor:self.termsContainer.leadingAnchor],
[self.termsWebView.trailingAnchor constraintEqualToAnchor:self.termsContainer.trailingAnchor],
[self.termsWebView.trailingAnchor constraintEqualToAnchor:self.termsContainer.trailingAnchor],
[self.termsWebView.bottomAnchor constraintEqualToAnchor:self.termsContainer.bottomAnchor],
[self.termsWebView.bottomAnchor constraintEqualToAnchor:self.termsContainer.bottomAnchor],
[self.agreeButton.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:40],
[self.agreeButton.leadingAnchor constraintEqualToAnchor:self.termsOverlay.leadingAnchor constant:40],
[self.agreeButton.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-40],
[self.agreeButton.trailingAnchor constraintEqualToAnchor:self.termsOverlay.trailingAnchor constant:-40],
[self.agreeButton.bottomAnchor constraintEqualToAnchor:self.termsOverlay.safeAreaLayoutGuide.bottomAnchor constant:-20],
[self.agreeButton.bottomAnchor constraintEqualToAnchor:self.termsOverlay.safeAreaLayoutGuide.bottomAnchor constant:-20],
...
@@ -243,7 +257,6 @@
...
@@ -243,7 +257,6 @@
]];
]];
}
}
#pragma mark - Labels
#pragma mark - Labels
- (void)setupLabels:(UIView *)parent {
- (void)setupLabels:(UIView *)parent {
self.unitLabel = [[UILabel alloc] init];
self.unitLabel = [[UILabel alloc] init];
...
@@ -450,7 +463,7 @@
...
@@ -450,7 +463,7 @@
#pragma mark - api
#pragma mark - api
- (void)requestAppointment {
- (void)requestAppointment {
[APIClient requestAppointment:^(NSDictionary *data, NSError *error) {
[APIClient requestAppointment:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) return;
if (error) return;
if (!data[@"Data"]) return;
if (!data[@"Data"]) return;
...
@@ -477,34 +490,35 @@
...
@@ -477,34 +490,35 @@
NSArray *slots = selectedTypeDict[@"slots"] ?: @[];
NSArray *slots = selectedTypeDict[@"slots"] ?: @[];
self.allSlots = slots; // store all raw slots
self.allSlots = slots; // store all raw slots
// --- 3️⃣ Load Terms HTML ---
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSString *termsHTML = selectedTypeDict[@"terms"] ?: @"";
if (!self.termsAndCondition) {
NSString *styledHTML = [NSString stringWithFormat:
NSString *termsHTML = selectedTypeDict[@"terms"] ?: @"";
@"
<html>
"
NSLog(@"termsHTML: %@", termsHTML);
"
<head>
"
NSString *styledHTML = [NSString stringWithFormat:
"
<meta
name=
\"viewport\"
content=
\"width=device-width,
initial-scale=
1.0,
maximum-scale=
1.0\"
>
"
@"
<html>
"
"
<style>
"
"
<head>
"
"
body
{
font-size
:
14px
;
font-family
:
-apple-system
;
line-height
:
1.5
;
padding
:
12px
;
background-color
:
#F9F9F9
;
color
:
#000000
;
}
"
"
<meta
name=
\"viewport\"
content=
\"width=device-width,
initial-scale=
1.0,
maximum-scale=
1.0\"
>
"
"
p
,
div
,
span
,
li
{
color
:
#000000
!important
;
}
"
"
<style>
"
"
p
{
margin-bottom
:
12px
;
}
"
"
body
{
font-size
:
16px
;
font-family
:
-apple-system
;
line-height
:
1.5
;
padding
:
12px
;
background-color
:
#F9F9F9
;
color
:
#000000
;
}
"
"
</style>
"
"
p
,
div
,
span
,
li
{
color
:
#000000
!important
;
}
"
"
</head>
"
"
p
{
margin-bottom
:
12px
;
}
"
"
<body>
%@
</body>
"
"
</style>
"
"
</html>
", termsHTML];
"
</head>
"
"
<body>
%@
</body>
"
"
</html>
", termsHTML];
self.termsAndCondition = styledHTML;
dispatch_async(dispatch_get_main_queue(), ^{
[self.termsWebView loadHTMLString:styledHTML baseURL:nil];
self.termsAndCondition = styledHTML;
[self buildMarkedDatesFromSlots:slots];
}
[self.calendarView.collectionView reloadData];
[self.termsContainer layoutIfNeeded];
});
[self.termsWebView layoutIfNeeded];
[self.termsWebView loadHTMLString:self.termsAndCondition baseURL:nil];
});
}];
}];
}
}
-(void) requestGeneralInfo {
-(void) requestGeneralInfo {
[APIClient requestGeneralInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestGeneralInfo:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) return;
if (error) return;
NSDictionary *generalInfo = data[@"Data"];
NSDictionary *generalInfo = data[@"Data"];
...
@@ -705,7 +719,7 @@
...
@@ -705,7 +719,7 @@
dispatch_group_t
group =
dispatch_group_create();
dispatch_group_t
group =
dispatch_group_create();
dispatch_group_enter
(
group
);
dispatch_group_enter
(
group
);
[
APIClient
requestAppointment:
^(
NSDictionary
*
data
,
NSError
*
error
)
{
[
APIClient
requestAppointment:
^(
BOOL
success
,
NSDictionary
*
data
,
NSError
*
error
)
{
if
(
data
[@"
Data
"])
{
if
(
data
[@"
Data
"])
{
NSDictionary
*
dataDict =
data[@"Data"];
NSDictionary
*
dataDict =
data[@"Data"];
self
.
appointmentData =
dataDict;
self
.
appointmentData =
dataDict;
...
@@ -730,7 +744,7 @@
...
@@ -730,7 +744,7 @@
}];
}];
dispatch_group_enter(group);
dispatch_group_enter(group);
[APIClient requestGeneralInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestGeneralInfo:^(
BOOL success,
NSDictionary *data, NSError *error) {
id reps = data[@"Data"][@"representative"];
id reps = data[@"Data"][@"representative"];
self.representativeList = [reps isKindOfClass:[NSArray class]] ? reps : @[];
self.representativeList = [reps isKindOfClass:[NSArray class]] ? reps : @[];
dispatch_group_leave(group);
dispatch_group_leave(group);
...
...
framework/QmsPluginFramework/QmsPluginFramework/Appointment/AppointmentViewMoreViewController.mm
View file @
82cef0dc
...
@@ -927,7 +927,7 @@
...
@@ -927,7 +927,7 @@
- (void)requestDashboardInfo {
- (void)requestDashboardInfo {
[self.loadingView startAnimating];
[self.loadingView startAnimating];
[APIClient requestDashboardInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestDashboardInfo:^(
BOOL success,
NSDictionary *data, NSError *error) {
[self.loadingView stopAnimating];
[self.loadingView stopAnimating];
...
...
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/DashboardViewController.h
View file @
82cef0dc
...
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
...
@@ -19,6 +19,7 @@ NS_ASSUME_NONNULL_BEGIN
@property
(
nonatomic
,
copy
)
NSString
*
projectName
;
@property
(
nonatomic
,
copy
)
NSString
*
projectName
;
@property
(
nonatomic
,
copy
)
NSString
*
projectId
;
@property
(
nonatomic
,
copy
)
NSString
*
projectId
;
@property
(
nonatomic
,
copy
)
NSString
*
drawingPlanId
;
@property
(
nonatomic
,
copy
)
NSString
*
drawingPlanId
;
@property
(
nonatomic
,
copy
)
NSString
*
projectLogo
;
@end
@end
...
...
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/DashboardViewController.mm
View file @
82cef0dc
This diff is collapsed.
Click to expand it.
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/GeneralInfoViewController.mm
View file @
82cef0dc
...
@@ -541,7 +541,7 @@ typedef struct {
...
@@ -541,7 +541,7 @@ typedef struct {
#pragma mark - api
#pragma mark - api
- (void)requestGeneralInfo {
- (void)requestGeneralInfo {
[APIClient requestGeneralInfo:^(NSDictionary *data, NSError *error) {
[APIClient requestGeneralInfo:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error || !data) {
if (error || !data) {
NSLog(@"❌ General info error: %@", error.localizedDescription);
NSLog(@"❌ General info error: %@", error.localizedDescription);
return;
return;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/ProjectViewController.mm
View file @
82cef0dc
...
@@ -155,34 +155,49 @@
...
@@ -155,34 +155,49 @@
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
ProjectCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ProjectCardCell"
ProjectCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ProjectCardCell"
forIndexPath:indexPath];
forIndexPath:indexPath];
// Default placeholder
cell.imageView.image = [UIImage systemImageNamed:@"photo"];
cell.imageView.image = [UIImage systemImageNamed:@"photo"];
NSDictionary *project = self.projects[indexPath.item];
NSDictionary *project = self.projects[indexPath.item];
// Project name
// Project name
cell.nameLabel.text = project[@"project_name"];
id projectName = project[@"project_name"];
cell.nameLabel.text = [projectName isKindOfClass:[NSString class]] ? projectName : @"";
// Project logo
NSString *logoURLString = project[@"logo"] ?: project[@"logo_thumbnail"];
// Get logo URL safely
NSURL *url = [NSURL URLWithString:logoURLString];
NSString *logo = project[@"logo"];
NSString *thumb = project[@"logo_thumbnail"];
// Async load image (simple placeholder approach)
NSIndexPath *currentIndexPath = indexPath;
NSString *logoURLString = (logo.length > 0) ? logo :
(thumb.length > 0) ? thumb : nil;
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = data ? [UIImage imageWithData:data] : nil;
NSURL *url = [NSURL URLWithString:logoURLString ?: @""];
dispatch_async(dispatch_get_main_queue(), ^{
// Async load image safely
NSIndexPath *visibleIndexPath = [collectionView indexPathForCell:cell];
if (url) {
if (visibleIndexPath && visibleIndexPath.item == currentIndexPath.item) {
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
cell.imageView.image = image ?: [UIImage systemImageNamed:@"photo"];
completionHandler:^(NSData * _Nullable data,
}
NSURLResponse * _Nullable response,
});
NSError * _Nullable error) {
});
UIImage *image = data ? [UIImage imageWithData:data] : nil;
if (!image) return; // leave placeholder
dispatch_async(dispatch_get_main_queue(), ^{
// Only update if the cell is still visible at this indexPath
ProjectCardCell *updateCell = (ProjectCardCell *)[collectionView cellForItemAtIndexPath:indexPath];
if (updateCell) {
updateCell.imageView.image = image;
}
});
}];
[task resume];
}
return cell;
return cell;
}
}
...
@@ -194,6 +209,7 @@
...
@@ -194,6 +209,7 @@
vc.projectName = project[@"project_name"];
vc.projectName = project[@"project_name"];
vc.units = project[@"unit"];
vc.units = project[@"unit"];
vc.drawerController = self.drawerController;
vc.drawerController = self.drawerController;
vc.projectLogo = project[@"logo"] ?: project[@"logo_thumbnail"];
vc.modalPresentationStyle = UIModalPresentationFullScreen;
vc.modalPresentationStyle = UIModalPresentationFullScreen;
[self.navigationController pushViewController:vc animated:YES];
[self.navigationController pushViewController:vc animated:YES];
...
@@ -212,7 +228,7 @@
...
@@ -212,7 +228,7 @@
#pragma mark - API
#pragma mark - API
- (void)requestProjectList {
- (void)requestProjectList {
[APIClient requestProjectList:^(NSDictionary *data, NSError *error) {
[APIClient requestProjectList:^(
BOOL success,
NSDictionary *data, NSError *error) {
// debug
// debug
NSString *plainText = [NSString stringWithFormat:@"%@", data];
NSString *plainText = [NSString stringWithFormat:@"%@", data];
...
@@ -259,7 +275,7 @@
...
@@ -259,7 +275,7 @@
}
}
- (void)requestCompanyCode {
- (void)requestCompanyCode {
[APIClient requestCompanyCode:@"kita" completion:^(NSDictionary *data, NSError *error) {
[APIClient requestCompanyCode:@"kita" completion:^(
BOOL success,
NSDictionary *data, NSError *error) {
// debug
// debug
NSString *plainText = [NSString stringWithFormat:@"%@", data];
NSString *plainText = [NSString stringWithFormat:@"%@", data];
...
...
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/UnitViewController.h
View file @
82cef0dc
...
@@ -13,5 +13,6 @@
...
@@ -13,5 +13,6 @@
@property
(
nonatomic
,
copy
)
NSString
*
projectId
;
@property
(
nonatomic
,
copy
)
NSString
*
projectId
;
@property
(
nonatomic
,
copy
)
NSString
*
projectName
;
@property
(
nonatomic
,
copy
)
NSString
*
projectName
;
@property
(
nonatomic
,
copy
)
NSArray
*
units
;
@property
(
nonatomic
,
copy
)
NSArray
*
units
;
@property
(
nonatomic
,
copy
)
NSString
*
projectLogo
;
@end
@end
framework/QmsPluginFramework/QmsPluginFramework/Dashboard/UnitViewController.mm
View file @
82cef0dc
...
@@ -260,13 +260,14 @@ didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
@@ -260,13 +260,14 @@ didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *projectId = [unit[@"project_id"] description];
NSString *projectId = [unit[@"project_id"] description];
NSString *drawingPlanId = [unit[@"id"] description];
NSString *drawingPlanId = [unit[@"id"] description];
NSLog(@"self.projectLogo: %@", self.projectLogo);
DashboardViewController *vc = [[DashboardViewController alloc] init];
DashboardViewController *vc = [[DashboardViewController alloc] init];
vc.projectCode = unit[@"name"] ?: @"";
vc.projectCode = unit[@"name"] ?: @"";
vc.projectName = self.projectName;
vc.projectName = self.projectName;
vc.projectId = projectId ?: @"";
vc.projectId = projectId ?: @"";
vc.drawingPlanId = drawingPlanId ?: @"";
vc.drawingPlanId = drawingPlanId ?: @"";
vc.drawerController = self.drawerController;
vc.drawerController = self.drawerController;
vc.projectLogo = self.projectLogo;
vc.modalPresentationStyle = UIModalPresentationFullScreen;
vc.modalPresentationStyle = UIModalPresentationFullScreen;
[self.navigationController pushViewController:vc animated:YES];
[self.navigationController pushViewController:vc animated:YES];
}
}
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/AddInfoViewController.mm
View file @
82cef0dc
...
@@ -597,7 +597,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
...
@@ -597,7 +597,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
// ✅ JSON ONLY
// ✅ JSON ONLY
[APIClient submitAddInfo:self.issueID
[APIClient submitAddInfo:self.issueID
remarks:self.commentTextView.text
remarks:self.commentTextView.text
completion:^(NSDictionary *response, NSError *error) {
completion:^(
BOOL success,
NSDictionary *response, NSError *error) {
[self handleSubmitResponse:response error:error];
[self handleSubmitResponse:response error:error];
}];
}];
return;
return;
...
@@ -607,7 +607,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
...
@@ -607,7 +607,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
images:images
images:images
mediaURL:self.selectedMediaURL
mediaURL:self.selectedMediaURL
mediaType:mediaType
mediaType:mediaType
completion:^(NSDictionary *response, NSError *error) {
completion:^(
BOOL success,
NSDictionary *response, NSError *error) {
[self handleSubmitResponse:response error:error];
[self handleSubmitResponse:response error:error];
}];
}];
}
}
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/AddIssue/DetailsViewController.mm
View file @
82cef0dc
...
@@ -957,7 +957,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
...
@@ -957,7 +957,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
[APIClient submitUpdateIssue:updateData
[APIClient submitUpdateIssue:updateData
images:self.addedImages
images:self.addedImages
completion:^(
NSDictionary * _Nullable response, NSError * _Nullable error)
{
completion:^(
BOOL success, NSDictionary *response, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
if (error) {
[self showAlertWithTitle:@"Update Failed" message:error.localizedDescription];
[self showAlertWithTitle:@"Update Failed" message:error.localizedDescription];
...
@@ -1043,7 +1043,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
...
@@ -1043,7 +1043,7 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
[APIClient submitAddIssue:issueData
[APIClient submitAddIssue:issueData
images:self.uploadedImages
images:self.uploadedImages
completion:^(NSDictionary *response, NSError *error) {
completion:^(
BOOL success,
NSDictionary *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
if (error) {
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/AddIssue/PlanViewController.mm
View file @
82cef0dc
...
@@ -69,7 +69,7 @@
...
@@ -69,7 +69,7 @@
- (void)handleGetUnitPlan {
- (void)handleGetUnitPlan {
NSLog(@"🌐 requesting Unit Plan data...");
NSLog(@"🌐 requesting Unit Plan data...");
[APIClient requestGetUnitPlan:^(NSDictionary *data, NSError *error) {
[APIClient requestGetUnitPlan:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"❌ Unit Plan request failed: %@", error.localizedDescription);
NSLog(@"❌ Unit Plan request failed: %@", error.localizedDescription);
return;
return;
...
@@ -710,7 +710,7 @@
...
@@ -710,7 +710,7 @@
- (void)handleSettingsByLocation:(NSString *)locationID planID:(NSString *)planID {
- (void)handleSettingsByLocation:(NSString *)locationID planID:(NSString *)planID {
[APIClient requestSettingsByLocation:locationID
[APIClient requestSettingsByLocation:locationID
completion:^(NSDictionary *data, NSError *error) {
completion:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"❌ Error requesting settings: %@", error);
NSLog(@"❌ Error requesting settings: %@", error);
return;
return;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/HistoryViewController.mm
View file @
82cef0dc
...
@@ -127,7 +127,7 @@
...
@@ -127,7 +127,7 @@
#pragma mark - API request/response
#pragma mark - API request/response
- (void)handleIssues {
- (void)handleIssues {
[APIClient requestHistory:self.issueID
[APIClient requestHistory:self.issueID
completion:^(NSDictionary *data, NSError *error) {
completion:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"❌ Error requesting history: %@", error);
NSLog(@"❌ Error requesting history: %@", error);
return;
return;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/IssuesViewController.mm
View file @
82cef0dc
...
@@ -300,7 +300,7 @@
...
@@ -300,7 +300,7 @@
- (void)handleGetIssue {
- (void)handleGetIssue {
NSLog(@"🌐 requesting Issue data...");
NSLog(@"🌐 requesting Issue data...");
[APIClient requestIssues:^(NSDictionary *data, NSError *error) {
[APIClient requestIssues:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"❌ Issue request failed: %@", error.localizedDescription);
NSLog(@"❌ Issue request failed: %@", error.localizedDescription);
return;
return;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/WithdrawIssuesViewController.mm
View file @
82cef0dc
...
@@ -286,7 +286,7 @@
...
@@ -286,7 +286,7 @@
[searchContainer.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:50],
[searchContainer.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:50],
[searchContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:8],
[searchContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:8],
[searchContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-8],
[searchContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-8],
[searchContainer.heightAnchor constraintEqualToConstant:1
0
0],
[searchContainer.heightAnchor constraintEqualToConstant:1
2
0],
[self.searchBar.leadingAnchor constraintEqualToAnchor:searchContainer.leadingAnchor],
[self.searchBar.leadingAnchor constraintEqualToAnchor:searchContainer.leadingAnchor],
[self.searchBar.trailingAnchor constraintEqualToAnchor:searchContainer.trailingAnchor],
[self.searchBar.trailingAnchor constraintEqualToAnchor:searchContainer.trailingAnchor],
...
@@ -383,7 +383,7 @@
...
@@ -383,7 +383,7 @@
#pragma mark - Data
#pragma mark - Data
- (void)requestIssues {
- (void)requestIssues {
[APIClient requestIssues:^(NSDictionary *data, NSError *error) {
[APIClient requestIssues:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) return;
if (error) return;
NSArray *allIssues = data[@"Data"] ?: @[];
NSArray *allIssues = data[@"Data"] ?: @[];
...
...
framework/QmsPluginFramework/QmsPluginFramework/Issue/WithdrawSingleIssueViewController.mm
View file @
82cef0dc
...
@@ -264,7 +264,7 @@
...
@@ -264,7 +264,7 @@
- (void)requestDeleteIssue:(NSString *)issueID remarks:(NSString *)remarks {
- (void)requestDeleteIssue:(NSString *)issueID remarks:(NSString *)remarks {
NSLog(@"🚀 Sending DELETE ISSUE for ID=%@, remarks=%@", issueID, remarks);
NSLog(@"🚀 Sending DELETE ISSUE for ID=%@, remarks=%@", issueID, remarks);
[APIClient requestDeleteIssue:issueID remarks:remarks completion:^(NSDictionary *data, NSError *error) {
[APIClient requestDeleteIssue:issueID remarks:remarks completion:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"Error %@", error.localizedDescription);
NSLog(@"Error %@", error.localizedDescription);
return;
return;
...
@@ -303,7 +303,7 @@
...
@@ -303,7 +303,7 @@
[APIClient requestVoidIssue:ids
[APIClient requestVoidIssue:ids
remarks:remarks
remarks:remarks
completion:^(NSDictionary *data, NSError *error) {
completion:^(
BOOL success,
NSDictionary *data, NSError *error) {
if (error) {
if (error) {
NSLog(@"Error %@", error.localizedDescription);
NSLog(@"Error %@", error.localizedDescription);
return;
return;
...
...
framework/QmsPluginFramework/QmsPluginFramework/Sync/SyncProjectViewController.mm
View file @
82cef0dc
...
@@ -105,6 +105,7 @@ UICollectionViewDataSource
...
@@ -105,6 +105,7 @@ UICollectionViewDataSource
@implementation SyncProjectViewController
@implementation SyncProjectViewController
- (void)viewDidLoad {
- (void)viewDidLoad {
[super viewDidLoad];
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
self.projects = [NSMutableArray array];
self.projects = [NSMutableArray array];
self.selectedUnits = [NSMutableArray array];
self.selectedUnits = [NSMutableArray array];
...
@@ -480,7 +481,7 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
...
@@ -480,7 +481,7 @@ didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self showLoading:YES];
[self showLoading:YES];
[APIClient requestProjectList:^(NSDictionary *data, NSError *error) {
[APIClient requestProjectList:^(
BOOL success,
NSDictionary *data, NSError *error) {
// debug
// debug
NSString *plainText = [NSString stringWithFormat:@"%@", data];
NSString *plainText = [NSString stringWithFormat:@"%@", data];
...
...
framework/QmsPluginFramework/QmsPluginFramework/Utilities/API/APIClient.h
View file @
82cef0dc
...
@@ -8,22 +8,22 @@ NS_ASSUME_NONNULL_BEGIN
...
@@ -8,22 +8,22 @@ NS_ASSUME_NONNULL_BEGIN
+
(
void
)
requestAccessItem
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestAccessItem
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestGetUnitPlan
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestGetUnitPlan
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestSettingsByLocation
:(
NSString
*
_Nonnull
)
locationID
+
(
void
)
requestSettingsByLocation
:(
NSString
*
_Nonnull
)
locationID
completion
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
submitAddIssue
:(
NSDictionary
*
_Nonnull
)
params
+
(
void
)
submitAddIssue
:(
NSDictionary
*
_Nonnull
)
params
images
:(
NSArray
<
UIImage
*>
*
_Nullable
)
images
images
:(
NSArray
<
UIImage
*>
*
_Nullable
)
images
completion
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
submitUpdateIssue
:(
NSDictionary
*
_Nonnull
)
updateData
+
(
void
)
submitUpdateIssue
:(
NSDictionary
*
_Nonnull
)
updateData
images
:(
NSArray
<
UIImage
*>
*
_Nullable
)
images
images
:(
NSArray
<
UIImage
*>
*
_Nullable
)
images
completion
:(
void
(
^
)(
NSDictionary
*
_Nullable
response
,
NSError
*
_Nullable
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestAppointment
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestAppointment
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestGeneralInfo
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestGeneralInfo
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
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
;
...
@@ -33,52 +33,52 @@ NS_ASSUME_NONNULL_BEGIN
...
@@ -33,52 +33,52 @@ NS_ASSUME_NONNULL_BEGIN
+
(
void
)
requestCancelAppointment
:(
id
)
appointmentId
+
(
void
)
requestCancelAppointment
:(
id
)
appointmentId
reason
:(
NSString
*
)
reason
reason
:(
NSString
*
)
reason
completion
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestDashboardInfo
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
requestDashboardInfo
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestAnnouncement
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
requestAnnouncement
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestHistory
:(
NSString
*
)
issueID
+
(
void
)
requestHistory
:(
NSString
*
)
issueID
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
submitAddInfo
:(
NSString
*
)
issueID
+
(
void
)
submitAddInfo
:(
NSString
*
)
issueID
remarks
:(
NSString
*
)
remarks
remarks
:(
NSString
*
)
remarks
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
uploadAddInfo
:(
NSString
*
)
issueID
+
(
void
)
uploadAddInfo
:(
NSString
*
)
issueID
remarks
:(
NSString
*
)
remarks
remarks
:(
NSString
*
)
remarks
images
:(
NSArray
<
UIImage
*>
*
)
images
images
:(
NSArray
<
UIImage
*>
*
)
images
mediaURL
:(
NSURL
*
)
mediaURL
mediaURL
:(
NSURL
*
)
mediaURL
mediaType
:(
NSString
*
)
mediaType
mediaType
:(
NSString
*
)
mediaType
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestIssues
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
+
(
void
)
requestIssues
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestVoidIssue
:(
id
)
issueID
+
(
void
)
requestVoidIssue
:(
id
)
issueID
remarks
:(
NSString
*
)
remarks
remarks
:(
NSString
*
)
remarks
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestDeleteIssue
:(
id
)
issueID
+
(
void
)
requestDeleteIssue
:(
id
)
issueID
remarks
:(
NSString
*
)
remarks
remarks
:(
NSString
*
)
remarks
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestCommonArea
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestCommonArea
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestGeneralSettings
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestGeneralSettings
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestDefectMatrix
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestDefectMatrix
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestProjectList
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
+
(
void
)
requestProjectList
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
requestArrayImage
:(
NSArray
*
)
imageArray
+
(
void
)
requestArrayImage
:(
NSArray
*
)
imageArray
completion
:(
void
(
^
)(
NSDictionary
*
data
,
NSError
*
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
+
(
void
)
downloadAndCacheImage
:(
NSURL
*
)
url
+
(
void
)
downloadAndCacheImage
:(
NSURL
*
)
url
completion
:(
void
(
^
)(
BOOL
success
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSString
*
filePath
))
completion
;
+
(
void
)
requestCompanyCode
:(
NSString
*
)
companyCode
+
(
void
)
requestCompanyCode
:(
NSString
*
)
companyCode
completion
:(
void
(
^
)(
NSDictionary
*
_Nullable
data
,
NSError
*
_Nullable
error
))
completion
;
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
error
))
completion
;
@end
@end
...
...
framework/QmsPluginFramework/QmsPluginFramework/Utilities/API/APIClient.mm
View file @
82cef0dc
This diff is collapsed.
Click to expand it.
framework/QmsPluginFramework/QmsPluginFramework/Utilities/API/APIConfig.h
View file @
82cef0dc
...
@@ -33,6 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
...
@@ -33,6 +33,13 @@ NS_ASSUME_NONNULL_BEGIN
/// JSON string form (what your APIs expect)
/// JSON string form (what your APIs expect)
+
(
NSString
*
)
deviceInfoJSONString
;
+
(
NSString
*
)
deviceInfoJSONString
;
//Offline
+
(
BOOL
)
handleOfflineForAPI
:(
NSString
*
)
apiName
completion
:(
void
(
^
)(
BOOL
success
,
NSDictionary
*
_Nullable
response
,
NSError
*
_Nullable
error
))
completion
;
//Null
+
(
NSDictionary
*
)
dictionaryByReplacingNullsWithBlanks
:(
NSDictionary
*
)
dict
;
@end
@end
NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_END
...
...
framework/QmsPluginFramework/QmsPluginFramework/Utilities/API/APIConfig.mm
View file @
82cef0dc
// APIConfig.mm
// APIConfig.mm
#import "APIConfig.h"
#import "APIConfig.h"
#import "LocalStorage.h"
#import "NetworkManager.h"
static NSString *kBaseURL = @"https://kitadev.commudesk.com/api";
static NSString *kBaseURL = @"https://kitadev.commudesk.com/api";
static NSString *kDrawingPlanId = @"";
static NSString *kDrawingPlanId = @"";
...
@@ -89,4 +91,67 @@ static NSString *kAuthToken = @"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI
...
@@ -89,4 +91,67 @@ static NSString *kAuthToken = @"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
#pragma mark - Offline Handling
+ (BOOL)handleOfflineForAPI:(NSString *)apiName
completion:(void(^)(BOOL success, NSDictionary * _Nullable response, NSError * _Nullable error))completion {
NSString *cacheKey =
[NSString stringWithFormat:@"%@_%@", apiName, [self projectId]];
if (![NetworkManager.sharedManager isConnected]) {
NSDictionary *cached = [LocalStorage loadDictionaryForKey:cacheKey];
if (cached) {
NSLog(@"🟡 Loaded from cache: %@", cacheKey);
if (completion) completion(YES, cached, nil);
} else {
NSError *offlineErr =
[NSError errorWithDomain:@"OfflineError"
code:-1
userInfo:@{
NSLocalizedDescriptionKey:
@"No network and no cached data"
}];
if (completion) completion(NO, nil, offlineErr);
}
return YES; // offline handled
}
return NO; // proceed with online request
}
#pragma mark - Null Handling
+ (NSDictionary *)dictionaryByReplacingNullsWithBlanks:(NSDictionary *)dict {
NSMutableDictionary *result = [NSMutableDictionary dictionary];
for (NSString *key in dict) {
id value = dict[key];
if (value == [NSNull null]) {
result[key] = @""; // or NSNull-safe replacement
} else if ([value isKindOfClass:[NSDictionary class]]) {
result[key] = [self dictionaryByReplacingNullsWithBlanks:value];
} else if ([value isKindOfClass:[NSArray class]]) {
result[key] = [self arrayByReplacingNullsWithBlanks:value];
} else {
result[key] = value;
}
}
return result;
}
+ (NSArray *)arrayByReplacingNullsWithBlanks:(NSArray *)array {
NSMutableArray *result = [NSMutableArray array];
for (id obj in array) {
if (obj == [NSNull null]) {
[result addObject:@""]; // or other safe value
} else if ([obj isKindOfClass:[NSDictionary class]]) {
[result addObject:[self dictionaryByReplacingNullsWithBlanks:obj]];
} else if ([obj isKindOfClass:[NSArray class]]) {
[result addObject:[self arrayByReplacingNullsWithBlanks:obj]];
} else {
[result addObject:obj];
}
}
return result;
}
@end
@end
framework/QmsPluginFramework/QmsPluginFramework/Utilities/OfflineSync/OfflineSyncManager.mm
View file @
82cef0dc
This diff is collapsed.
Click to expand it.
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