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

AddIssueDetails api progress

parent 1c3bdce0
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
......
// AddIssueAPIClient.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface AddIssueAPIClient : NSObject
+ (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
......@@ -90,8 +90,9 @@
[task resume];
}
+ (void)fetchSettingsByLocation:(void (^)(NSDictionary *data, NSError *error))completion{
// ✅ Build URL
+ (void)fetchSettingsByLocation:(NSString *)locationID
projectID:(NSString *)projectID
completion:(void (^)(NSDictionary *data, NSError *error))completion {
NSString *urlString = @"https://kitadev.commudesk.com/api/issue/getGeneralSettingByLocation?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImF0aGlyYWh6YWlkaUBjb252ZXAuY29tIiwicGFzc3dvcmQiOiIkMnkkMTAkNU9xYklqMnZ6UHJwckJrcVd5c3I2LmJCc1hVYS9Hd014eUhnL3RhUUhPUkNQcGdmTG8yakciLCJzdWIiOjIxNzAsImlzcyI6Imh0dHBzOi8va2l0YWRldi5jb21tdWRlc2suY29tL2FwaS9vd25lci9hdXRoL3Bhc3N3b3JkbGVzc19sb2dpbiIsImlhdCI6MTc2MDMxNTM1MiwiZXhwIjoyMDc1ODg0ODcyLCJuYmYiOjE3NjAzMTUzNTIsImp0aSI6IktoQmNyQnJEdDVNdDZlWmMifQ.JnxGbZ7hTeoOr6oibIzZMphgyKtTo2Aq9Efx6mrGfFA";
NSURL *url = [NSURL URLWithString:urlString];
......@@ -118,8 +119,8 @@
// 🧩 Add POST fields
appendFormField(@"data[os]", @"AND");
appendFormField(@"data[project_id]", @"8");
appendFormField(@"data[location_id]", @"1458"); //temp number
appendFormField(@"data[project_id]", projectID ?: @"0");
appendFormField(@"data[location_id]", locationID ?: @"0");
NSString *deviceInfo = @"{\"OS\":\"AND\",\"IMEI\":\"AND:2a2f13ff17b1cbb5\",\"OS_VERSION\":\"35\",\"MODEL\":\"2306EPN60G\",\"APP_VERSION\":\"1.22.26\"}";
appendFormField(@"data[information]", deviceInfo);
......@@ -177,6 +178,91 @@
[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 @@
@property (nonatomic, strong) NSString *projectCode;
@property (nonatomic, strong) NSString *projectName;
@property (nonatomic, assign) CGFloat planX;
@property (nonatomic, assign) CGFloat planY;
- (void)dismissSelf;
- (void)handleSubmit;
- (void)handleReset;
@end
#import "DetailsViewController.h"
#import "AddIssueAPIClient.h"
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@interface AddIssueDetailsViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (nonatomic, strong) UIView *headerView;
......@@ -10,12 +13,10 @@
@property (nonatomic, strong) NSArray *categories;
@property (nonatomic, strong) NSArray *types;
@property (nonatomic, strong) NSArray *issues;
@property (nonatomic, weak) UIButton *typeButton;
@property (nonatomic, weak) UIButton *issueButton;
@property (nonatomic, copy) NSString *selectedTypeName;
@property (nonatomic, copy) NSString * selectedIssueID;
@end
......@@ -25,13 +26,17 @@
[super viewDidLoad];
self.view.backgroundColor = UIColor.whiteColor;
NSLog(@"📦 Data received in AddIssueDetailsViewController:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@\n locationData: %@",
self.planID,
self.locationID,
self.selectedLocationName,
self.defectMatrix,
self.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.locationID,
self.selectedLocationName,
self.defectMatrix,
self.projectName,
self.projectCode,
self.planX,
self.planY,
self.locationData);
NSDictionary *locData = self.locationData;
if ([locData isKindOfClass:[NSDictionary class]]) {
self.categories = locData[@"category"];
......@@ -227,14 +232,14 @@
[locationTitle.topAnchor constraintEqualToAnchor:lastView.bottomAnchor constant:spacing].active = YES;
[locationTitle.leadingAnchor constraintEqualToAnchor:forLabel.leadingAnchor].active = YES;
UIView *locationContainer = [self makeRoundedBox];
[content addSubview:locationContainer];
[NSLayoutConstraint activateConstraints:@[
[locationContainer.topAnchor constraintEqualToAnchor:locationTitle.bottomAnchor constant:8],
[locationContainer.leadingAnchor constraintEqualToAnchor:content.leadingAnchor constant:20],
[locationContainer.trailingAnchor constraintEqualToAnchor:content.trailingAnchor constant:-20],
[locationContainer.heightAnchor constraintEqualToConstant:44],
]];
UIView *locationContainer = [self makeRoundedBox];
[content addSubview:locationContainer];
[NSLayoutConstraint activateConstraints:@[
[locationContainer.topAnchor constraintEqualToAnchor:locationTitle.bottomAnchor constant:8],
[locationContainer.leadingAnchor constraintEqualToAnchor:content.leadingAnchor constant:20],
[locationContainer.trailingAnchor constraintEqualToAnchor:content.trailingAnchor constant:-20],
[locationContainer.heightAnchor constraintEqualToConstant:44],
]];
// === Location Field (read-only) ===
UITextField *locationField = [[UITextField alloc] init];
......@@ -251,7 +256,7 @@
[locationField.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
]];
// === Reselect Button (below the container, left-aligned) ===
// === Reselect Button (inside the container, right-aligned) ===
UIButton *reselectBtn = [UIButton buttonWithType:UIButtonTypeSystem];
reselectBtn.translatesAutoresizingMaskIntoConstraints = NO;
[reselectBtn setTitle:@"Reselect" forState:UIControlStateNormal];
......@@ -259,13 +264,15 @@
forState:UIControlStateNormal];
reselectBtn.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[reselectBtn addTarget:self action:@selector(dismissSelf) forControlEvents:UIControlEventTouchUpInside];
[content addSubview:reselectBtn];
[locationContainer addSubview:reselectBtn];
[NSLayoutConstraint activateConstraints:@[
[reselectBtn.topAnchor constraintEqualToAnchor:locationContainer.bottomAnchor constant:4],
[reselectBtn.leadingAnchor constraintEqualToAnchor:locationContainer.leadingAnchor constant:4],
[reselectBtn.trailingAnchor constraintEqualToAnchor:locationContainer.trailingAnchor constant:-8],
[reselectBtn.centerYAnchor constraintEqualToAnchor:locationContainer.centerYAnchor],
// shrink locationField width so it doesn’t overlap
[locationField.trailingAnchor constraintEqualToAnchor:reselectBtn.leadingAnchor constant:-8],
]];
lastView = locationContainer;
// Category, Type, Issue — dropdown style
NSArray *titles = @[@"*Category", @"*Type", @"*Issue"];
......@@ -302,12 +309,13 @@
NSArray *categories = self.locationData[@"category"];
if (categories.count > 0) {
NSDictionary *firstCategory = categories.firstObject;
NSString *categoryName = firstCategory[@"cat_name"] ?: @"";
NSString *categoryName = locationField.text ?: @"";
[dropdown setTitle:categoryName forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
} else {
[dropdown setTitle:@"(No Category)" forState:UIControlStateNormal];
[dropdown setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
}
dropdown.enabled = NO; // make it non-clickable
......@@ -444,6 +452,7 @@
return btn;
}
- (void)handleDropdownTap:(UIButton *)sender {
NSInteger tag = sender.tag;
NSString *title = sender.titleLabel.text ?: @"Select";
......@@ -498,19 +507,40 @@
// Build alert actions
for (NSString *opt in options) {
[menu addAction:[UIAlertAction actionWithTitle:opt
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[sender setTitle:opt forState:UIControlStateNormal];
[sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
if (tag == 2001) { // Type
self.selectedTypeName = opt;
// Reset issue button when type changes
[self.issueButton setTitle:@"- Select Issue -" forState:UIControlStateNormal];
[self.issueButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
}
}]];
[menu addAction:[UIAlertAction actionWithTitle:opt
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[sender setTitle:opt forState:UIControlStateNormal];
[sender setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
if (tag == 2001) {
// === Type dropdown ===
self.selectedTypeName = opt;
self.selectedIssueID = nil; // reset previous issue selection
[self.issueButton setTitle:@"- Select Issue -" 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;
}
}
}
}]];
}
[menu addAction:[UIAlertAction actionWithTitle:@"Cancel"
......@@ -711,11 +741,39 @@ didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *
}
- (void)handleSubmit {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Submitted"
message:@"Issue has been added (mock)."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
NSLog(@"Calling addIssue API:\n planID: %@\n locationID: %@\n selectedIssueID: %@\n XCoordinates: %f\n YCoordinates: %f\n commentField: %@",
self.planID,
self.locationID,
self.selectedIssueID,
self.planX,
self.planY,
self.commentField);
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
......@@ -30,6 +30,10 @@
@property (nonatomic, strong) NSString *locationID;
@property (nonatomic, strong) NSDictionary *locationData;
@property (nonatomic, strong) NSString *defectMatrix;
@property (nonatomic, strong) NSDictionary *unitPlanResponse;
@property (nonatomic, strong) NSArray *unitPlanLocations;
@property (nonatomic, assign) CGFloat tappedPlanX;
@property (nonatomic, assign) CGFloat tappedPlanY;
@end
......@@ -46,7 +50,7 @@
self.overlayLayers = [NSMutableArray array];
[self fetchInitialData];
[self handleGetUnitPlan];
[self.view bringSubviewToFront:self.headerView];
}
......@@ -61,7 +65,7 @@
}
}
- (void)fetchInitialData {
- (void)handleGetUnitPlan {
NSLog(@"🌐 Fetching Unit Plan data...");
[AddIssueAPIClient fetchGetUnitPlan:^(NSDictionary *data, NSError *error) {
......@@ -78,6 +82,9 @@
NSString *filePath = [docsPath stringByAppendingPathComponent:@"getUnitPlan.txt"];
[jsonData writeToFile:filePath atomically:YES];
NSLog(@"📁 UnitPlan saved to %@", filePath);
// 🔹 Save the full API response
self.unitPlanResponse = data;
// 🔍 Parse JSON
NSDictionary *appData = data[@"AppData"];
......@@ -91,6 +98,7 @@
NSLog(@"⚠️ No unit plan data found");
return;
}
self.unitPlanLocations = mainData.firstObject[@"location"];
// Store main plan object
self.unitPlanData = mainData.firstObject;
......@@ -113,7 +121,6 @@
NSString *widthStr = [NSString stringWithFormat:@"%@", firstIssue[@"plan_width"]];
NSString *heightStr = [NSString stringWithFormat:@"%@", firstIssue[@"plan_height"]];
self.planID = [NSString stringWithFormat:@"%@", firstIssue[@"plan_id"] ?: @"0"];
self.locationID = [NSString stringWithFormat:@"%@", firstIssue[@"location_id"] ?: @"0"];
self.planWidth = [widthStr floatValue];
self.planHeight = [heightStr floatValue];
......@@ -122,7 +129,7 @@
NSLog(@"📐 Plan dimensions: width = %f, height = %f", self.planWidth, self.planHeight);
NSLog(@"🗺 Found %lu locations", (unsigned long)self.locations.count);
NSLog(@"🖼 Plan image URL: %@", self.planImageURL);
NSLog(@"🧭 plan_id = %@, location_id = %@", self.planID, self.locationID);
NSLog(@"🧭 plan_id = %@ ", self.planID);
// Update UI on main thread
dispatch_async(dispatch_get_main_queue(), ^{
......@@ -179,12 +186,25 @@
if (self.selectionLocked) return;
CGPoint tapPoint = [recognizer locationInView:self.planImageView];
NSLog(@"👆 User tapped at: %@", NSStringFromCGPoint(tapPoint));
NSLog(@"👆 User tapped on screen at: %@", NSStringFromCGPoint(tapPoint));
// Remove previous marker (if any)
[self.markerView removeFromSuperview];
// Get image display rect and scaling ratios
CGRect imageRect = [self imageRectInImageView:self.planImageView];
CGFloat displayedWidth = imageRect.size.width;
CGFloat displayedHeight = imageRect.size.height;
CGFloat scaleX = displayedWidth / self.planWidth;
CGFloat scaleY = displayedHeight / self.planHeight;
// Add new marker
// 🔹 Convert back to original plan coordinates
CGFloat planX = (tapPoint.x - imageRect.origin.x) / scaleX;
CGFloat planY = (tapPoint.y - imageRect.origin.y) / scaleY;
NSLog(@"🧭 Original plan coordinates: (%.2f, %.2f)", planX, planY);
self.tappedPlanX = planX;
self.tappedPlanY = planY;
// Optional: Visual marker
[self.markerView removeFromSuperview];
UIView *marker = [[UIView alloc] initWithFrame:CGRectMake(tapPoint.x - 6, tapPoint.y - 6, 12, 12)];
marker.backgroundColor = [UIColor redColor];
marker.layer.cornerRadius = 6;
......@@ -193,23 +213,19 @@
[self.planImageView addSubview:marker];
self.markerView = marker;
// Check if tap inside any polygon
// Continue with polygon detection
for (int i = 0; i < self.locations.count; i++) {
NSDictionary *locationData = self.locations[i];
CAShapeLayer *overlay = self.overlayLayers[i];
if ([self isPoint:tapPoint insideLocation:locationData]) {
NSLog(@"✅ Tap inside location: %@", locationData[@"name"]);
// Selected: Red border
overlay.strokeColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.8].CGColor;
self.selectedOverlay = overlay;
self.selectionLocked = YES;
self.selectedLocation = locationData[@"name"];
[self showAddIssuePopup];
} else {
// Non-selected: Gray border, no fill
overlay.strokeColor = [UIColor colorWithWhite:0.6 alpha:0.5].CGColor;
overlay.fillColor = UIColor.clearColor.CGColor;
}
......@@ -377,69 +393,6 @@
});
}
- (void)handleUnitPlanResponse:(NSDictionary *)data {
NSLog(@"🧩 Handling Unit Plan response...");
NSDictionary *appData = data[@"AppData"];
NSArray *mainData = data[@"Data"];
// 🧱 Step 1 — Check for maintenance
if ([appData[@"error_code"] integerValue] == 503) {
NSLog(@"⚠️ Maintenance mode");
[self showAlertWithTitle:@"Maintenance Mode" message:@"System under maintenance. Please try again later."];
return;
}
// 🧱 Step 2 — If status is success
if ([appData[@"status"] isEqualToString:@"success"]) {
if (mainData.count > 0) {
NSDictionary *unitPlan = mainData.firstObject;
self.unitPlanData = unitPlan;
// ✅ Extract and store plan dimensions (ensure they’re numeric)
NSString *widthStr = [NSString stringWithFormat:@"%@", unitPlan[@"plan_width"]];
NSString *heightStr = [NSString stringWithFormat:@"%@", unitPlan[@"plan_height"]];
self.planWidth = [widthStr floatValue];
self.planHeight = [heightStr floatValue];
NSLog(@"📏 planWidth = %f, planHeight = %f", self.planWidth, self.planHeight);
// 🧱 Safety check
if (self.planWidth <= 0 || self.planHeight <= 0) {
NSLog(@"⚠️ Invalid plan dimensions — overlays may not render correctly.");
}
// Save JSON for debugging
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString *filePath = [docsPath stringByAppendingPathComponent:@"unitPlanParsed.json"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:unitPlan options:NSJSONWritingPrettyPrinted error:nil];
[jsonData writeToFile:filePath atomically:YES];
NSLog(@"📁 Parsed unit plan saved to %@", filePath);
// 🖼 Step 3 — Load image if available
NSString *planImageURL = unitPlan[@"plan_image"];
if (planImageURL.length > 0) {
[self loadPlanImageFromURL:planImageURL];
} else {
NSLog(@"⚠️ No plan_image found in response");
}
// ✅ Update title
NSString *unitName = unitPlan[@"unit_name"] ?: @"No name";
dispatch_async(dispatch_get_main_queue(), ^{
self.titleLabel.text = unitName;
});
}
} else {
// 🧱 Step 4 — Handle error response
NSString *message = appData[@"message"] ?: @"Unknown error.";
if ([message isEqualToString:@"user_not_found"]) {
[self showAlertWithTitle:@"Session Expired" message:@"Please log in again."];
} else {
[self showAlertWithTitle:@"Error" message:message];
}
}
}
- (void)createScrollView {
self.scrollView = [[UIScrollView alloc] init];
......@@ -510,12 +463,6 @@
if (i == 0) [path moveToPoint:CGPointMake(x, y)];
else [path addLineToPoint:CGPointMake(x, y)];
// 🔵 Visual dot marker
// UIView *dot = [[UIView alloc] initWithFrame:CGRectMake(x - 2, y - 2, 4, 4)];
// dot.backgroundColor = [UIColor blueColor];
// dot.layer.cornerRadius = 2;
// [planImageView addSubview:dot];
NSLog(@"📍 Point %d -> x=%f, y=%f", i, x, y);
if (x < imageRect.origin.x || y < imageRect.origin.y ||
......@@ -669,9 +616,37 @@
self.selectionLocked = NO;
[self dismissAddIssuePopup];
[AddIssueAPIClient fetchSettingsByLocation:^(NSDictionary *data, NSError *error) {
// Hide loader once we have a result
// === 1️⃣ Find the matching location ID ===
NSString *selectedName = self.selectedLocation;
NSLog(@"self.unitPlanLocation: %@, self.selectedLocation: %@", self.unitPlanLocations, self.selectedLocation);
for (NSDictionary *loc in self.unitPlanLocations) {
NSString *locName = loc[@"location_name"] ?: loc[@"name"];
NSString *locID = [NSString stringWithFormat:@"%@", loc[@"location_id"] ?: loc[@"id"]];
if ([locName isEqualToString:self.selectedLocation]) {
self.locationID = locID;
NSLog(@"✅ Matched location: %@ → ID %@", locName, locID);
break;
}
}
if (self.locationID) {
NSLog(@"📡 Fetching settings for location %@ and plan %@", self.locationID, self.planID);
[self handleSettingsByLocation:self.locationID planID:self.planID];
} else {
NSLog(@"⚠️ No match found for %@", self.selectedLocation);
}
}
- (void)handleSettingsByLocation:(NSString *)locationID planID:(NSString *)planID {
[AddIssueAPIClient fetchSettingsByLocation:locationID
projectID:@"8"
completion:^(NSDictionary *data, NSError *error) {
if (error) {
NSLog(@"❌ Error fetching settings: %@", error);
return;
......@@ -683,12 +658,12 @@
// === 1️⃣ Basic error checks ===
if (statusCode && statusCode.intValue != 200 && statusCode.intValue != 0) {
NSLog(@"Error, Server returned %@", statusCode);
NSLog(@"Error, Server returned %@", statusCode);
return;
}
if ([appData[@"error_code"] integerValue] == 503) {
NSLog(@"Maintenance Mode, Server temporarily unavailable");
NSLog(@"Maintenance Mode, Server temporarily unavailable");
return;
}
......@@ -696,33 +671,11 @@
if ([appData[@"status"] isEqualToString:@"success"] && mainData) {
NSLog(@"✅ Location settings loaded successfully");
// Determine defectMatrix flag
NSString *defectMatrix = mainData ? @"YES" : @"NO";
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
AddIssueDetailsViewController *nextVC = [[AddIssueDetailsViewController alloc] init];
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
NSLog(@"locationID %@ and planID %@", self.locationID, self.planID);
// ✅ Pass data forward
nextVC.planID = self.planID;
nextVC.locationID = self.locationID;
nextVC.selectedLocationName = self.selectedLocation;
nextVC.locationData = mainData;
nextVC.defectMatrix = defectMatrix;
nextVC.projectCode = self.projectCode;
nextVC.projectName = self.projectName;
NSLog(@"📦 Data being brought over:\n planID: %@\n locationID: %@\n selectedLocationName: %@\n defectMatrix: %@\n projectName: %@\n projectCode: %@\n locationData: %@",
nextVC.planID,
nextVC.locationID,
nextVC.selectedLocationName,
nextVC.defectMatrix,
nextVC.projectName,
nextVC.projectCode,
nextVC.locationData);
[self presentViewController:nextVC animated:YES completion:nil];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
[self navigateToAddIssueDetailsWithLocationData:mainData defectMatrix:defectMatrix];
});
return;
}
......@@ -731,22 +684,43 @@
NSString *message = appData[@"message"] ?: @"Unknown server response.";
if ([message isEqualToString:@"user_not_found"]) {
NSLog(@"Session Expired, Please log in again");
// Optionally trigger logout flow here
} else if ([message.lowercaseString containsString:@"defect matrix not found"] ||
[message.lowercaseString containsString:@"location not found"]) {
// Proceed anyway but with defectMatrix=NO
AddIssueDetailsViewController *nextVC = [[AddIssueDetailsViewController alloc] init];
nextVC.planID = self.planID;
nextVC.locationID = self.locationID;
nextVC.selectedLocationName = self.selectedLocation;
nextVC.defectMatrix = @"NO";
[self presentViewController:nextVC animated:YES completion:nil];
[self navigateToAddIssueDetailsWithLocationData:nil defectMatrix:@"NO"];
} else {
NSLog(@"Error %@", message);
NSLog(@"Error %@", message);
}
}];
}
- (void)navigateToAddIssueDetailsWithLocationData:(NSDictionary *)mainData defectMatrix:(NSString *)defectMatrix {
AddIssueDetailsViewController *nextVC = [[AddIssueDetailsViewController alloc] init];
nextVC.modalPresentationStyle = UIModalPresentationFullScreen;
nextVC.planID = self.planID;
nextVC.locationID = self.locationID;
nextVC.selectedLocationName = self.selectedLocation;
nextVC.locationData = mainData;
nextVC.defectMatrix = defectMatrix;
nextVC.projectCode = self.projectCode;
nextVC.projectName = self.projectName;
nextVC.planX = self.tappedPlanX;
nextVC.planY = self.tappedPlanY;
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: %@",
nextVC.planID,
nextVC.locationID,
nextVC.selectedLocationName,
nextVC.defectMatrix,
nextVC.projectName,
nextVC.projectCode,
nextVC.planX,
nextVC.planY,
nextVC.locationData);
[self presentViewController:nextVC animated:YES completion:nil];
}
#pragma mark - Actions
- (void)handleBack {
......
......@@ -8,32 +8,32 @@
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>QmsPluginFramework.framework/QmsPluginFramework</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>QmsPluginFramework.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<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