-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[INSPECT-340][FEATURE] - added scroll feature to validation #341
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,57 +17,34 @@ class Alert { | |
and return call back when user makes selection | ||
*/ | ||
static func show(title: String, message: String, yes: @escaping()-> Void, no: @escaping()-> Void) { | ||
//self.showDefaultAlert(title: title, message: message, yes: yes, no: no) | ||
self.showCustomAlert(title: title, message: message, yes: yes, no: no); | ||
self.showCustomAlert(title: title, message: message, yes: yes, no: no) | ||
} | ||
|
||
/** | ||
Show an alert message with an okay button | ||
*/ | ||
static func show(title: String, message: String) { | ||
//self.showDefaultAlert(title: title, message: message) | ||
self.showCustomAlert(title: title, message: message); | ||
ModalAlert.show(title: title, message: message) | ||
} | ||
|
||
// MARK: Default iOS alerts | ||
private static func showDefaultAlert(title: String, message: String, yes: @escaping()-> Void, no: @escaping()-> Void) { | ||
DispatchQueue.main.async(execute: { | ||
let alertWindow = UIWindow(frame: UIScreen.main.bounds) | ||
alertWindow.rootViewController = UIViewController() | ||
alertWindow.windowLevel = UIWindow.Level.alert + 1 | ||
|
||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) | ||
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { action in | ||
return yes(); | ||
})) | ||
alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { action in | ||
return no(); | ||
})) | ||
|
||
alertWindow.makeKeyAndVisible() | ||
alertWindow.rootViewController?.present(alert, animated: true, completion: nil) | ||
}) | ||
/** | ||
Show a validation alert message for inspections | ||
*/ | ||
static func showValidation(title: String, message: String) { | ||
if let topVC = UIApplication.shared.windows.first?.rootViewController?.topMostViewController() { | ||
let alertVC = ScrollableAlertViewController() | ||
alertVC.modalPresentationStyle = .overFullScreen | ||
alertVC.modalTransitionStyle = .crossDissolve | ||
alertVC.configure(title: title, message: message) | ||
topVC.present(alertVC, animated: true) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the function to render our inspection validation with the scroll ability |
||
} | ||
|
||
private static func showDefaultAlert(title: String, message: String) { | ||
DispatchQueue.main.async(execute: { | ||
let alertWindow = UIWindow(frame: UIScreen.main.bounds) | ||
alertWindow.rootViewController = UIViewController() | ||
alertWindow.windowLevel = UIWindow.Level.alert + 1 | ||
|
||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) | ||
let defaultAction2 = UIAlertAction(title: "OK", style: .default, handler: { action in | ||
}) | ||
alert.addAction(defaultAction2) | ||
|
||
alertWindow.makeKeyAndVisible() | ||
alertWindow.rootViewController?.present(alert, animated: true, completion: nil) | ||
}) | ||
} | ||
|
||
|
||
// MARK: Custom alerts using Modal pod | ||
private static func showCustomAlert(title: String, message: String, yes: @escaping()-> Void, no: @escaping()-> Void) { | ||
ModalAlert.show(title: title, message: message, yes: yes, no: no); | ||
ModalAlert.show(title: title, message: message, yes: yes, no: no) | ||
} | ||
|
||
private static func showCustomAlert(title: String, message: String) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Had to create a new class for this new alert message, rather than edit the existing class. |
||
// ScrollAlert.swift | ||
// ipad | ||
// | ||
// Created by Paul Garewal on 2024-12-19. | ||
// Copyright © 2024 Amir Shayegh. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
|
||
class ScrollableAlertViewController: UIViewController { | ||
|
||
private let titleLabel = UILabel() | ||
private let textView = UITextView() | ||
private let okButton = UIButton(type: .system) | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
setupView() | ||
} | ||
|
||
private func setupView() { | ||
// Configure background | ||
view.backgroundColor = UIColor.black.withAlphaComponent(0.5) | ||
|
||
// Container for the alert | ||
let alertContainer = UIView() | ||
alertContainer.backgroundColor = .white | ||
alertContainer.layer.cornerRadius = 12 | ||
alertContainer.translatesAutoresizingMaskIntoConstraints = false | ||
view.addSubview(alertContainer) | ||
|
||
// Title label | ||
titleLabel.font = .boldSystemFont(ofSize: 17) | ||
titleLabel.textColor = .black | ||
titleLabel.numberOfLines = 1 | ||
titleLabel.textAlignment = .center | ||
titleLabel.translatesAutoresizingMaskIntoConstraints = false | ||
alertContainer.addSubview(titleLabel) | ||
|
||
// Scrollable text view | ||
textView.isEditable = false | ||
textView.isScrollEnabled = true | ||
textView.font = .systemFont(ofSize: 14) | ||
textView.textColor = .black | ||
textView.backgroundColor = .clear | ||
textView.showsVerticalScrollIndicator = true | ||
textView.translatesAutoresizingMaskIntoConstraints = false | ||
alertContainer.addSubview(textView) | ||
|
||
// OK button | ||
okButton.setTitle("OK", for: .normal) | ||
okButton.titleLabel?.font = .systemFont(ofSize: 17, weight: .semibold) | ||
okButton.setTitleColor(.systemBlue, for: .normal) | ||
okButton.translatesAutoresizingMaskIntoConstraints = false | ||
okButton.contentEdgeInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) | ||
okButton.backgroundColor = .clear | ||
alertContainer.addSubview(okButton) | ||
okButton.addTarget(self, action: #selector(dismissAlert), for: .touchUpInside) | ||
|
||
NSLayoutConstraint.activate([ | ||
// Alert container | ||
alertContainer.centerXAnchor.constraint(equalTo: view.centerXAnchor), | ||
alertContainer.centerYAnchor.constraint(equalTo: view.centerYAnchor), | ||
alertContainer.widthAnchor.constraint(equalToConstant: 270), | ||
|
||
// Title label | ||
titleLabel.topAnchor.constraint(equalTo: alertContainer.topAnchor, constant: 16), | ||
titleLabel.leadingAnchor.constraint(equalTo: alertContainer.leadingAnchor, constant: 16), | ||
titleLabel.trailingAnchor.constraint(equalTo: alertContainer.trailingAnchor, constant: -16), | ||
|
||
// Text view | ||
textView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8), | ||
textView.leadingAnchor.constraint(equalTo: alertContainer.leadingAnchor, constant: 16), | ||
textView.trailingAnchor.constraint(equalTo: alertContainer.trailingAnchor, constant: -16), | ||
textView.heightAnchor.constraint(equalToConstant: 200), | ||
|
||
// OK button | ||
okButton.topAnchor.constraint(equalTo: textView.bottomAnchor, constant: 8), | ||
okButton.bottomAnchor.constraint(equalTo: alertContainer.bottomAnchor, constant: -8), | ||
okButton.leadingAnchor.constraint(equalTo: alertContainer.leadingAnchor), | ||
okButton.trailingAnchor.constraint(equalTo: alertContainer.trailingAnchor), | ||
okButton.heightAnchor.constraint(equalToConstant: 44) | ||
]) | ||
} | ||
|
||
@objc private func dismissAlert() { | ||
dismiss(animated: true) | ||
} | ||
|
||
func configure(title: String, message: String) { | ||
titleLabel.text = title | ||
textView.text = message | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -290,90 +290,81 @@ class ShiftViewController: BaseViewController { | |
} | ||
|
||
func validationMessage() -> String { | ||
var message: String = "" | ||
guard let model = self.model else { return message } | ||
var counter = 1 | ||
var messages: [String] = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file is general clean up and the adding of the emojis to the error messages |
||
guard let model = self.model else { return "" } | ||
|
||
// Group validation messages by category | ||
|
||
// Shift Time Validations | ||
if model.startTime.isEmpty { | ||
message = "\(message)\n\(counter)- Missing Shift Start time." | ||
counter += 1 | ||
messages.append("⏰ Shift Start time is required") | ||
} | ||
|
||
if model.endTime.isEmpty { | ||
message = "\(message)\n\(counter)- Missing Shift End time." | ||
counter += 1 | ||
messages.append("⏰ Shift End time is required") | ||
} | ||
|
||
// Inspection Count Validations | ||
if model.inspections.count > 0 && model.boatsInspected == false { | ||
message = "\(message)\n\(counter)- You indicated that no boats were inspected, but inspections exist." | ||
counter += 1 | ||
messages.append("⚠️ Inspection count mismatch: You indicated no boats were inspected, but inspections exist") | ||
} | ||
|
||
if model.inspections.count < 1 && model.boatsInspected == true { | ||
message = "\(message)\n\(counter)- You indicated that boats were inspected but inspections are missing." | ||
counter += 1 | ||
messages.append("⚠️ Inspection count mismatch: You indicated boats were inspected but no inspections are recorded") | ||
} | ||
|
||
// Station Validations | ||
if model.station.isEmpty { | ||
message = "\(message)\n\(counter)- Please choose a station." | ||
counter += 1 | ||
messages.append("📍 Station selection is required") | ||
} | ||
|
||
if model.stationComments.isEmpty && ShiftModel.stationRequired(model.station) { | ||
message = "\(message)\n\(counter)- Please add station information." | ||
counter += 1 | ||
messages.append("📍 Station information is required") | ||
} | ||
|
||
for inspection in model.inspections { | ||
// Inspection Detail Validations | ||
for (index, inspection) in model.inspections.enumerated() { | ||
if inspection.inspectionTime.isEmpty { | ||
message = "\(message)\n\(counter)- Missing Time of Inspection." | ||
counter += 1 | ||
messages.append("🕒 Inspection #\(index + 1): Time of inspection is required") | ||
} | ||
|
||
if inspection.unknownPreviousWaterBody == true || | ||
inspection.commercialManufacturerAsPreviousWaterBody == true || | ||
inspection.previousDryStorage == true { | ||
if inspection.previousMajorCities.isEmpty { | ||
message = "\(message)\n\(counter)- Please add Closest Major City for Previous Waterbody." | ||
counter += 1 | ||
} | ||
// Previous Waterbody Validations | ||
if (inspection.unknownPreviousWaterBody || | ||
inspection.commercialManufacturerAsPreviousWaterBody || | ||
inspection.previousDryStorage) { | ||
messages.append("🌊 Inspection #\(index + 1): Previous waterbody requires closest major city") | ||
} | ||
|
||
if inspection.unknownDestinationWaterBody == true || | ||
inspection.commercialManufacturerAsDestinationWaterBody == true || | ||
inspection.destinationDryStorage == true { | ||
if inspection.destinationMajorCities.isEmpty { | ||
message = "\(message)\n\(counter)- Please add Closest Major City for Destination Waterbody." | ||
counter += 1 | ||
} | ||
// Destination Waterbody Validations | ||
if (inspection.unknownDestinationWaterBody || | ||
inspection.commercialManufacturerAsDestinationWaterBody || | ||
inspection.destinationDryStorage) && inspection.destinationMajorCities.isEmpty { | ||
messages.append("🎯 Inspection #\(index + 1): Destination waterbody requires closest major city") | ||
} | ||
|
||
if !inspection.highRiskAssessments.isEmpty { | ||
for highRisk in inspection.highRiskAssessments { | ||
if highRisk.sealIssued == true && highRisk.sealNumber <= 0 { | ||
message = "\(message)\n\(counter)- Please input the Seal #." | ||
counter += 1 | ||
} | ||
|
||
if highRisk.decontaminationOrderIssued == true && highRisk.decontaminationOrderNumber <= 0 { | ||
message = "\(message)\n\(counter)- Please input the Decontamination order number." | ||
counter += 1 | ||
} | ||
// High Risk Assessment Validations | ||
for (riskIndex, highRisk) in inspection.highRiskAssessments.enumerated() { | ||
if highRisk.sealIssued && highRisk.sealNumber <= 0 { | ||
messages.append("🏷️ Inspection #\(index + 1) Risk #\(riskIndex + 1): Seal number is required") | ||
} | ||
|
||
if highRisk.decontaminationOrderIssued && highRisk.decontaminationOrderNumber <= 0 { | ||
messages.append("📄 Inspection #\(index + 1) Risk #\(riskIndex + 1): Decontamination order number is required") | ||
} | ||
} | ||
} | ||
|
||
// Check for invalid inspections | ||
// Form Validation Status | ||
let invalidInspections = model.inspections.filter { !$0.formDidValidate } | ||
if !invalidInspections.isEmpty { | ||
message = "\(message)\n\(counter)- One or more inspections contain validation errors. Please review each inspection." | ||
counter += 1 | ||
messages.append("❌ One or more inspections contain validation errors") | ||
} | ||
|
||
if !message.isEmpty { | ||
model.set(status: .Errors) | ||
} | ||
if !messages.isEmpty { | ||
model.set(status: .Errors) | ||
} | ||
|
||
return message | ||
return messages.joined(separator: "\n\n") | ||
} | ||
|
||
func createTestModel() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This helps show alerts regardless of navigation stack (helped to display our alert box in each window)