import SharedModels import SwiftUI public protocol FlaggedEquipmentMeasurementStyle { associatedtype Body: View typealias Configuration = FlaggedEquipmentMeasurementStyleConfiguration @ViewBuilder func makeBody(configuration: Self.Configuration) -> Self.Body } public struct FlaggedEquipmentMeasurementStyleConfiguration { public let measurement: FlaggedEquipmentMeasurement } public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle { private var _makeBody: (Configuration) -> AnyView internal init(makeBody: @escaping (Configuration) -> AnyView) { self._makeBody = makeBody } public init(_ style: S) { self.init { configuration in AnyView(style.makeBody(configuration: configuration)) } } public func makeBody(configuration: Configuration) -> some View { _makeBody(configuration) } } public struct GridFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle { public func makeBody(configuration: Configuration) -> some View { Grid(alignment: .leading, verticalSpacing: 20) { ForEach(FlaggedEquipmentMeasurement.Key.allCases) { field in FlaggedView( field.title, flagged: configuration.measurement[keyPath: field.flaggedKeyPath] ) .flaggedViewStyle(.gridRow(fractionLength: field == .airflow ? 0 : 2)) } } } } extension FlaggedEquipmentMeasurementStyle where Self == GridFlaggedEquipmentMeasurementStyle { public static var grid: Self { .init() } } private struct FlaggedEquipmentMeasurementStyleKey: EnvironmentKey { static let defaultValue = AnyFlaggedEquipmentMeasurementStyle(GridFlaggedEquipmentMeasurementStyle()) } extension EnvironmentValues { public var flaggedEquipmentMeasurementStyle: AnyFlaggedEquipmentMeasurementStyle { get { self[FlaggedEquipmentMeasurementStyleKey.self] } set { self[FlaggedEquipmentMeasurementStyleKey.self] = newValue } } } extension View { public func flaggedEquipmentMeasurementStyle(_ style: AnyFlaggedEquipmentMeasurementStyle) -> some View { environment(\.flaggedEquipmentMeasurementStyle, style) } public func flaggedEquipmentMeasurementStyle( _ style: S ) -> some View { flaggedEquipmentMeasurementStyle(AnyFlaggedEquipmentMeasurementStyle(style)) } } // MARK: - Key fileprivate extension FlaggedEquipmentMeasurement { // NOTE: These need to be kept in display order. enum Key: Hashable, CaseIterable, Identifiable { case returnPlenum case filterDrop case coilDrop case supplyPlenum case staticPressure case airflow var id: Self { self } var title: String { switch self { case .returnPlenum: return "Return Plenum" case .filterDrop: return "Filter Pressure Drop" case .coilDrop: return "Coil Pressure Drop" case .supplyPlenum: return "Supply Plenum" case .staticPressure: return "External Static Pressure" case .airflow: return "System Airflow" } } var flaggedKeyPath: KeyPath { switch self { case .returnPlenum: return \.returnPlenumPressure case .filterDrop: return \.filterPressureDrop case .coilDrop: return \.coilPressureDrop case .supplyPlenum: return \.supplyPlenumPressure case .staticPressure: return \.externalStaticPressure case .airflow: return \.airflow } } } }