Commit 3dd910fa authored by Wei Han's avatar Wei Han

AddIssueDetails api progress

parent 1c3bdce0
...@@ -8,32 +8,32 @@ ...@@ -8,32 +8,32 @@
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string> <string>ios-arm64</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
<dict> <dict>
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64</string> <string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
</array> </array>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
......
// AddIssueAPIClient.h // AddIssueAPIClient.h
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface AddIssueAPIClient : NSObject @interface AddIssueAPIClient : NSObject
+ (void)fetchGetUnitPlan:(void (^)(NSDictionary *data, NSError *error))completion; + (void)fetchGetUnitPlan:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)fetchSettingsByLocation:(void (^)(NSDictionary *data, NSError *error))completion; + (void)fetchSettingsByLocation:(NSString *)locationID
projectID:(NSString *)projectID
completion:(void (^)(NSDictionary *data, NSError *error))completion;
+ (void)submitAddIssue:(NSDictionary *)params
images:(NSArray<UIImage *> *)images
completion:(void (^)(NSDictionary *data, NSError *error))completion;
@end @end
...@@ -90,8 +90,9 @@ ...@@ -90,8 +90,9 @@
[task resume]; [task resume];
} }
+ (void)fetchSettingsByLocation:(void (^)(NSDictionary *data, NSError *error))completion{ + (void)fetchSettingsByLocation:(NSString *)locationID
// ✅ Build URL projectID:(NSString *)projectID
completion:(void (^)(NSDictionary *data, NSError *error))completion {
NSString *urlString = @"https://kitadev.commudesk.com/api/issue/getGeneralSettingByLocation?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA"; NSString *urlString = @"https://kitadev.commudesk.com/api/issue/getGeneralSettingByLocation?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA";
NSURL *url = [NSURL URLWithString:urlString]; NSURL *url = [NSURL URLWithString:urlString];
...@@ -118,8 +119,8 @@ ...@@ -118,8 +119,8 @@
// 🧩 Add POST fields // 🧩 Add POST fields
appendFormField(@"data[os]", @"AND"); appendFormField(@"data[os]", @"AND");
appendFormField(@"data[project_id]", @"8"); appendFormField(@"data[project_id]", projectID ?: @"0");
appendFormField(@"data[location_id]", @"1458"); //temp number appendFormField(@"data[location_id]", locationID ?: @"0");
NSString *deviceInfo = @"{\"OS\":\"AND\",\"IMEI\":\"AND:2a2f13ff17b1cbb5\",\"OS_VERSION\":\"35\",\"MODEL\":\"2306EPN60G\",\"APP_VERSION\":\"1.22.26\"}"; NSString *deviceInfo = @"{\"OS\":\"AND\",\"IMEI\":\"AND:2a2f13ff17b1cbb5\",\"OS_VERSION\":\"35\",\"MODEL\":\"2306EPN60G\",\"APP_VERSION\":\"1.22.26\"}";
appendFormField(@"data[information]", deviceInfo); appendFormField(@"data[information]", deviceInfo);
...@@ -177,6 +178,91 @@ ...@@ -177,6 +178,91 @@
[task resume]; [task resume];
} }
+ (void)submitAddIssue:(NSDictionary *)issueData
images:(NSArray<UIImage *> * _Nullable)images
completion:(void (^)(NSDictionary * _Nullable response, NSError * _Nullable error))completion {
@end NSString *urlString = @"https://kitadev.commudesk.com/api/owner/issue/addIssue?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA"; NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// 🧱 Multipart body
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]
forHTTPHeaderField:@"Content-Type"];
NSMutableData *body = [NSMutableData data];
// Helper for adding form fields
void (^appendFormField)(NSString *, NSString *) = ^(NSString *key, NSString *value) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", value]
dataUsingEncoding:NSUTF8StringEncoding]];
};
// 🔹 Append form data fields
for (NSString *key in issueData.allKeys) {
id value = issueData[key];
if ([value isKindOfClass:[NSNumber class]]) value = [(NSNumber *)value stringValue];
if ([value isKindOfClass:[NSString class]]) {
appendFormField([NSString stringWithFormat:@"data[%@]", key], value);
}
}
// 🔹 Append OS info
appendFormField(@"data[os]", @"AND");
// 🔹 Append images
if (images.count > 0) {
for (int i = 0; i < images.count; i++) {
UIImage *image = images[i];
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
if (!imageData) continue;
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:
@"Content-Disposition: form-data; name=\"data[image][%d]\"; filename=\"image%d.jpg\"\r\n", i, i]
dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imageData];
[body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
}
}
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary]
dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = body;
// Debug
NSLog(@"📦 [AddIssue] Uploading %lu image(s)", (unsigned long)images.count);
NSURLSessionDataTask *task = [[NSURLSession sharedSession]
dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"❌ [AddIssue] Network error: %@", error);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(nil, error); });
return;
}
NSError *jsonErr;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr];
if (jsonErr) {
NSString *raw = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"⚠️ [AddIssue] JSON parse error: %@\nRaw response: %@", jsonErr, raw);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(nil, jsonErr); });
return;
}
NSLog(@"✅ [AddIssue] Response: %@", json);
dispatch_async(dispatch_get_main_queue(), ^{ if (completion) completion(json, nil); });
}];
[task resume];
}
@end
...@@ -15,4 +15,11 @@ ...@@ -15,4 +15,11 @@
@property (nonatomic, strong) NSString *projectCode; @property (nonatomic, strong) NSString *projectCode;
@property (nonatomic, strong) NSString *projectName; @property (nonatomic, strong) NSString *projectName;
@property (nonatomic, assign) CGFloat planX;
@property (nonatomic, assign) CGFloat planY;
- (void)dismissSelf;
- (void)handleSubmit;
- (void)handleReset;
@end @end
#import "DetailsViewController.h" #import "DetailsViewController.h"
#import "AddIssueAPIClient.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface AddIssueDetailsViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate> @interface AddIssueDetailsViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (nonatomic, strong) UIView *headerView; @property (nonatomic, strong) UIView *headerView;
...@@ -10,12 +13,10 @@ ...@@ -10,12 +13,10 @@
@property (nonatomic, strong) NSArray *categories; @property (nonatomic, strong) NSArray *categories;
@property (nonatomic, strong) NSArray *types; @property (nonatomic, strong) NSArray *types;
@property (nonatomic, strong) NSArray *issues; @property (nonatomic, strong) NSArray *issues;
@property (nonatomic, weak) UIButton *typeButton; @property (nonatomic, weak) UIButton *typeButton;
@property (nonatomic, weak) UIButton *issueButton; @property (nonatomic, weak) UIButton *issueButton;
@property (nonatomic, copy) NSString *selectedTypeName; @property (nonatomic, copy) NSString *selectedTypeName;
@property (nonatomic, copy) NSString * selectedIssueID;
@end @end
...@@ -25,11 +26,15 @@ ...@@ -25,11 +26,15 @@
[super viewDidLoad]; [super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor; self.view.backgroundColor = UIColor.whiteColor;
NSLog(@"📦 Data received in AddIssueDetailsViewController:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@\n locationData: %@", NSLog(@"📦 Data being brought over:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@\n projectName: %@\n projectCode: %@\n XCoordinates: %f\n YCoordinates: %f\n locationData: %@",
self.planID, self.planID,
self.locationID, self.locationID,
self.selectedLocationName, self.selectedLocationName,
self.defectMatrix, self.defectMatrix,
self.projectName,
self.projectCode,
self.planX,
self.planY,
self.locationData); self.locationData);
NSDictionary *locData = self.locationData; NSDictionary *locData = self.locationData;
...@@ -251,7 +256,7 @@ ...@@ -251,7 +256,7 @@
[locationField.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor], [locationField.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
]]; ]];
// === Reselect Button (below the container, left-aligned) === // === Reselect Button (inside the container, right-aligned) ===
UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem]; UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
reselectBtn.translatesAutoresizingMaskIntoConstraints = NO; reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
[reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal]; [reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
...@@ -259,13 +264,15 @@ ...@@ -259,13 +264,15 @@
forState:UIControlStateNormal]; forState:UIControlStateNormal];
reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14]; reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside]; [reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
[content addSubview:reselectBtn]; [locationContainer addSubview:reselectBtn];
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[reselectBtn.topAnchor constraintEqualToAnchor:locationContainer.bottomAnchor constant:4], [reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
[reselectBtn.leadingAnchor constraintEqualToAnchor:locationContainer.leadingAnchor constant:4], [reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
// shrink locationField width so it doesn’t overlap
[locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
]]; ]];
lastView = locationContainer;
// Category, Type, Issue — dropdown style // Category, Type, Issue — dropdown style
NSArray *titles = @[@"*Category", @"*Type", @"*Issue"]; NSArray *titles = @[@"*Category", @"*Type", @"*Issue"];
...@@ -302,12 +309,13 @@ ...@@ -302,12 +309,13 @@
NSArray *categories = self.locationData[@"category"]; NSArray *categories = self.locationData[@"category"];
if (categories.count > 0) { if (categories.count > 0) {
NSDictionary *firstCategory = categories.firstObject; NSDictionary *firstCategory = categories.firstObject;
NSString *categoryName = firstCategory[@"cat_name"] ?: @""; NSString *categoryName = locationField.text ?: @"";
[dropdown setTitle:categoryName forState:UIControlStateNormal]; [dropdown setTitle:categoryName forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [dropdown setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
} else { } else {
[dropdown setTitle:@"(No Category)" forState:UIControlStateNormal]; [dropdown setTitle:@"(No Category)" forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; [dropdown setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
} }
dropdown.enabled = NO; // make it non-clickable dropdown.enabled = NO; // make it non-clickable
...@@ -444,6 +452,7 @@ ...@@ -444,6 +452,7 @@
return btn; return btn;
} }
- (void)handleDropdownTap:(UIButton *)sender { - (void)handleDropdownTap:(UIButton *)sender {
NSInteger tag = sender.tag; NSInteger tag = sender.tag;
NSString *title = sender.titleLabel.text ?: @"Select"; NSString *title = sender.titleLabel.text ?: @"Select";
...@@ -504,11 +513,32 @@ ...@@ -504,11 +513,32 @@
[sender setTitle:opt forState:UIControlStateNormal]; [sender setTitle:opt forState:UIControlStateNormal];
[sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
if (tag == 2001) { // Type if (tag == 2001) {
// === Type dropdown ===
self.selectedTypeName = opt; self.selectedTypeName = opt;
// Reset issue button when type changes self.selectedIssueID = nil; // reset previous issue selection
[self.issueButton setTitle:@"- Select Issue -" forState:UIControlStateNormal]; [self.issueButton setTitle:@"- Select Issue -" forState:UIControlStateNormal];
[self.issueButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; [self.issueButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
NSLog(@"✅ Selected Type: %@", self.selectedTypeName);
} else if (tag == 2002) {
// === Issue dropdown ===
NSArray *issuesForType = @[];
for (NSDictionary *type in self.types) {
if ([type[@"type_name"] isEqualToString:self.selectedTypeName]) {
issuesForType = type[@"issue"];
break;
}
}
for (NSDictionary *issue in issuesForType) {
NSString *issueName = issue[@"issue_name"];
if ([issueName isEqualToString:opt]) {
self.selectedIssueID = [NSString stringWithFormat:@"%@", issue[@"issue_id"]];
NSLog(@"✅ Selected Issue: %@ (ID: %@)", issueName, self.selectedIssueID);
break;
}
}
} }
}]]; }]];
} }
...@@ -711,11 +741,39 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> * ...@@ -711,11 +741,39 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
} }
- (void)handleSubmit { - (void)handleSubmit {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Submitted" NSLog(@"Calling addIssue API:\n planID: %@\n locationID: %@\n selectedIssueID: %@\n XCoordinates: %f\n YCoordinates: %f\n commentField: %@",
message:@"Issue has been added (mock)." self.planID,
preferredStyle:UIAlertControllerStyleAlert]; self.locationID,
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; self.selectedIssueID,
[self presentViewController:alert animated:YES completion:nil]; self.planX,
self.planY,
self.commentField);
NSDictionary *issueData = @{
@"plan_id": self.planID ?: @"0",
@"location_id": self.locationID ?: @"0",
@"issue_setting_id": self.selectedIssueID ?: @"",
@"position_x": [NSString stringWithFormat:@"%f", self.planX ?: 0.0],
@"position_y": [NSString stringWithFormat:@"%f", self.planY ?: 0.0],
@"comment": self.commentField ?: @"",
@"os": @"AND"
};
[AddIssueAPIClient submitAddIssue:issueData
images:self.uploadedImages
completion:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(@"❌ Submission failed: %@", error.localizedDescription);
return;
}
NSDictionary *appData = response[@"AppData"];
if ([appData[@"status"] isEqualToString:@"success"]) {
NSLog(@"✅ Issue submitted successfully!");
} else {
NSLog(@"⚠️ API Error: %@", appData[@"message"]);
}
}];
} }
@end @end
...@@ -8,32 +8,32 @@ ...@@ -8,32 +8,32 @@
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string> <string>ios-arm64</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
<dict> <dict>
<key>BinaryPath</key> <key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string> <string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key> <key>LibraryIdentifier</key>
<string>ios-arm64</string> <string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key> <key>LibraryPath</key>
<string>QmsPluginFramework.framework</string> <string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key> <key>SupportedArchitectures</key>
<array> <array>
<string>arm64</string> <string>arm64</string>
<string>x86_64</string>
</array> </array>
<key>SupportedPlatform</key> <key>SupportedPlatform</key>
<string>ios</string> <string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict> </dict>
</array> </array>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment