182 lines
5.1 KiB
Swift
182 lines
5.1 KiB
Swift
import SharedModels
|
|
import SwiftUI
|
|
|
|
public struct FlaggedEquipmentMeasurementView: View {
|
|
|
|
@Environment(\.flaggedEquipmentMeasurementStyle) private var style
|
|
|
|
let measurement: EquipmentMeasurement.FlaggedMeasurement
|
|
let ignoreIfZero: [EquipmentMeasurement.FlaggedMeasurement.FieldKey]
|
|
|
|
public init(
|
|
_ measurement: EquipmentMeasurement.FlaggedMeasurement,
|
|
ignoreIfZero: [EquipmentMeasurement.FlaggedMeasurement.FieldKey] = []
|
|
) {
|
|
self.measurement = measurement
|
|
self.ignoreIfZero = ignoreIfZero
|
|
}
|
|
|
|
public var body: some View {
|
|
style.makeBody(
|
|
configuration: FlaggedEquipmentMeasurementStyleConfiguration(
|
|
measurement: measurement,
|
|
ignoreIfZero: ignoreIfZero
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
public protocol FlaggedEquipmentMeasurementStyle {
|
|
associatedtype Body: View
|
|
typealias Configuration = FlaggedEquipmentMeasurementStyleConfiguration
|
|
|
|
@ViewBuilder
|
|
func makeBody(configuration: Self.Configuration) -> Self.Body
|
|
}
|
|
|
|
public struct FlaggedEquipmentMeasurementStyleConfiguration {
|
|
public let measurement: EquipmentMeasurement.FlaggedMeasurement
|
|
public let ignoreIfZero: [EquipmentMeasurement.FlaggedMeasurement.FieldKey]
|
|
}
|
|
|
|
public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle {
|
|
private var _makeBody: (Configuration) -> AnyView
|
|
|
|
internal init(makeBody: @escaping (Configuration) -> AnyView) {
|
|
self._makeBody = makeBody
|
|
}
|
|
|
|
public init<S: FlaggedEquipmentMeasurementStyle>(_ 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(EquipmentMeasurement.FlaggedMeasurement.FieldKey.allCases) { field in
|
|
if configuration.measurement[keyPath: field.flaggedKeyPath].wrappedValue == 0,
|
|
configuration.ignoreIfZero.contains(field)
|
|
{
|
|
EmptyView()
|
|
} else {
|
|
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<S: FlaggedEquipmentMeasurementStyle>(
|
|
_ style: S
|
|
) -> some View {
|
|
flaggedEquipmentMeasurementStyle(AnyFlaggedEquipmentMeasurementStyle(style))
|
|
}
|
|
}
|
|
|
|
// MARK: - FieldKey
|
|
extension EquipmentMeasurement.FlaggedMeasurement {
|
|
// NOTE: These need to be kept in display order.
|
|
public enum FieldKey: Hashable, CaseIterable, Identifiable {
|
|
case returnPlenum
|
|
case filterDrop
|
|
case coilDrop
|
|
case supplyPlenum
|
|
case staticPressure
|
|
case airflow
|
|
|
|
public 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<EquipmentMeasurement.FlaggedMeasurement, Flagged> {
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if DEBUG
|
|
private let equipmentMeasurement = EquipmentMeasurement.airHandler(.init(
|
|
airflow: 1600,
|
|
manufacturersIncludedFilterPressureDrop: 0.1,
|
|
returnPlenumPressure: 0.37,
|
|
postFilterPressure: 0.78,
|
|
postCoilPressure: 0.9,
|
|
supplyPlenumPressure: 0.11
|
|
))
|
|
|
|
#Preview {
|
|
NavigationStack {
|
|
FlaggedEquipmentMeasurementView(
|
|
.init(
|
|
budgets: .init(equipmentType: .airHandler, fanType: .variableSpeed),
|
|
measurement: equipmentMeasurement,
|
|
ratedPressures: .init(),
|
|
tons: .four
|
|
)
|
|
)
|
|
.padding()
|
|
}
|
|
}
|
|
#endif
|