diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 0f339285..f04b2a77 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -153,6 +153,8 @@ 444FB7C12821B73200DFE692 /* TitleLockup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C02821B73200DFE692 /* TitleLockup.swift */; }; 444FB7C32821B76B00DFE692 /* TitleLockupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */; }; 4457904E27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */; }; + 446396222A3C3F8F00FB547C /* TimeDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 446396212A3C3F8F00FB547C /* TimeDropdownEntryField.swift */; }; + 446396242A3C3F9D00FB547C /* TimeDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 446396232A3C3F9D00FB547C /* TimeDropdownEntryFieldModel.swift */; }; 522679C123FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */; }; 522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */; }; 52267A0723FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */; }; @@ -760,6 +762,8 @@ 444FB7C02821B73200DFE692 /* TitleLockup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockup.swift; sourceTree = ""; }; 444FB7C22821B76B00DFE692 /* TitleLockupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TitleLockupModel.swift; sourceTree = ""; }; 4457904D27ECE989002B1E1E /* UIImageRenderingMode+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImageRenderingMode+Extension.swift"; sourceTree = ""; }; + 446396212A3C3F8F00FB547C /* TimeDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeDropdownEntryField.swift; sourceTree = ""; }; + 446396232A3C3F9D00FB547C /* TimeDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeDropdownEntryFieldModel.swift; sourceTree = ""; }; 522679BF23FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinks.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinks.swift; sourceTree = ""; }; 522679C023FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableCheckboxAllTextAndLinksModel.swift; sourceTree = ""; }; 52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinks.swift; sourceTree = ""; }; @@ -1328,6 +1332,7 @@ children = ( 0A7EF86223D8AFA000B2AAD1 /* BaseDropdownFieldModel.swift */, 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */, + 446396202A3C3F7300FB547C /* Time Dropdown */, 0A0FEC8D25D4487F00AF2548 /* Date Dropdown */, 0A0FEC8A25D4486F00AF2548 /* Item Dropdown */, ); @@ -1436,6 +1441,15 @@ path = Behaviors; sourceTree = ""; }; + 446396202A3C3F7300FB547C /* Time Dropdown */ = { + isa = PBXGroup; + children = ( + 446396232A3C3F9D00FB547C /* TimeDropdownEntryFieldModel.swift */, + 446396212A3C3F8F00FB547C /* TimeDropdownEntryField.swift */, + ); + path = "Time Dropdown"; + sourceTree = ""; + }; 5206F150241144A900658DC5 /* Headers */ = { isa = PBXGroup; children = ( @@ -2693,6 +2707,7 @@ 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */, D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */, + 446396222A3C3F8F00FB547C /* TimeDropdownEntryField.swift in Sources */, 32F8804824765C8400C2ACB3 /* ListLeftVariableNumberedListAllTextAndLinks.swift in Sources */, D2CAC7CF2511052300C75681 /* CollapsableNotificationModel.swift in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, @@ -3177,6 +3192,7 @@ D2FA83D42514F80C00564112 /* CollapsableNotification.swift in Sources */, 0A7EF86323D8AFA000B2AAD1 /* BaseDropdownFieldModel.swift in Sources */, 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */, + 446396242A3C3F9D00FB547C /* TimeDropdownEntryFieldModel.swift in Sources */, D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */, D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryField.swift new file mode 100644 index 00000000..ea5322fd --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryField.swift @@ -0,0 +1,115 @@ +// +// TimeDropdownEntryField.swift +// MVMCoreUI +// +// Created by Nadigadda, Sumanth on 16/06/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class TimeDropdownEntryField: BaseDropdownEntryField { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public weak var timePicker: UIDatePicker? + + private var calendar: Calendar = { + var calendar: Calendar = .current + calendar.timeZone = NSTimeZone.system + return calendar + }() + + public var timeFormat: String? { + get { timeDropdownModel?.timeFormat } + set { + guard let newValue = newValue else { return } + timeDropdownModel?.timeFormat = newValue + } + } + + public var timeDropdownModel: TimeDropdownEntryFieldModel? { + model as? TimeDropdownEntryFieldModel + } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + @objc public override init(frame: CGRect) { + super.init(frame: frame) + } + + @objc public convenience init() { + self.init(frame: .zero) + } + + @objc required public init?(coder: NSCoder) { + fatalError("TimeDropdownEntryField init(coder:) has not been implemented") + } + + required public init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.init(model: model, delegateObject, additionalData) + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public override func setupFieldContainerContent(_ container: UIView) { + super.setupFieldContainerContent(container) + + timePicker = UIDatePicker.addTimeAndDatePicker(to: textField) + timePicker?.addTarget(self, action: #selector(pickerValueChanged), for: .valueChanged) + timePicker?.timeZone = NSTimeZone.system + textField.inputView = timePicker + UIToolbar.addDismissToolbar(to: textField, delegate: self, action: #selector(dismissFieldInput)) + } + + @objc public func dismissDatePicker() -> Date? { + + let pickedTime = timePicker?.date + setTextWith(date: pickedTime) + resignFirstResponder() + return pickedTime + } + + @objc private func setTextWith(date: Date?) { + + guard let date = date else { return } + timeDropdownModel?.date = date + text = timeDropdownModel?.timeFormatter.string(from: date) + } + + @objc public override func dismissFieldInput(_ sender: Any?) { + + setTextWith(date: timePicker?.date) + super.dismissFieldInput(sender) + } + + @objc func pickerValueChanged(_ sender: UIDatePicker) { + setTextWith(date: timePicker?.date) + } + + //-------------------------------------------------- + // MARK: - MoleculeViewProtocol + //-------------------------------------------------- + + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.set(with: model, delegateObject, additionalData) + + guard let model = model as? TimeDropdownEntryFieldModel else { return } + + if let date = model.time { + timePicker?.date = date + setTextWith(date: timePicker?.date) + } + } + + public override func reset() { + super.reset() + text = nil + } + +} diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryFieldModel.swift new file mode 100644 index 00000000..081d0b19 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Time Dropdown/TimeDropdownEntryFieldModel.swift @@ -0,0 +1,71 @@ +// +// TimeDropdownEntryFieldModel.swift +// MVMCoreUI +// +// Created by Nadigadda, Sumanth on 16/06/23. +// Copyright © 2023 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class TimeDropdownEntryFieldModel: BaseDropdownEntryFieldModel { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public override class var identifier: String { "timeDropdownEntryField" } + + public var timeFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.timeStyle = .medium + formatter.timeZone = NSTimeZone.system + formatter.locale = .current + formatter.formatterBehavior = .default + return formatter + }() + + /// Update the property value to alter the format of how the date is presented. + public var timeFormat: String = "hh:mm a" { + didSet { timeFormatter.dateFormat = timeFormat } + } + + public var time: Date? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case time + case timeFormat + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + try super.init(from: decoder) + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + + if let timeFormat = try typeContainer.decodeIfPresent(String.self, forKey: .timeFormat) { + self.timeFormat = timeFormat + timeFormatter.dateFormat = timeFormat + } + + if let time = try typeContainer.decodeIfPresent(String.self, forKey: .time) { + baseValue = time + self.time = timeFormatter.date(from: time) + } + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(timeFormat, forKey: .timeFormat) + + if let time = time { + try container.encode(timeFormatter.string(from: time), forKey: .time) + } + } +} diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index 11108eeb..9bdfec21 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -44,6 +44,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: ItemDropdownEntryField.self, for: ItemDropdownEntryFieldModel.self) ModelRegistry.register(handler: DateDropdownEntryField.self, for: DateDropdownEntryFieldModel.self) ModelRegistry.register(handler: MultiItemDropdownEntryField.self, for: MultiItemDropdownEntryFieldModel.self) + ModelRegistry.register(handler: TimeDropdownEntryField.self, for: TimeDropdownEntryFieldModel.self) // MARK:- Selectors ModelRegistry.register(handler: RadioButton.self, for: RadioButtonModel.self)