Files
swift-estimated-pressures-core/Sources/FlaggedViews/FlaggedEquipmentMeasurementView.swift

169 lines
4.6 KiB
Swift

import SharedModels
import SwiftUI
public struct FlaggedEquipmentMeasurementView: View {
@Environment(\.flaggedEquipmentMeasurementStyle) private var style
let measurement: EquipmentMeasurement.FlaggedMeasurement
public init(_ measurement: EquipmentMeasurement.FlaggedMeasurement) {
self.measurement = measurement
}
public var body: some View {
style.makeBody(
configuration: FlaggedEquipmentMeasurementStyleConfiguration(
measurement: measurement
)
)
}
}
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 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.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<S: FlaggedEquipmentMeasurementStyle>(
_ style: S
) -> some View {
flaggedEquipmentMeasurementStyle(AnyFlaggedEquipmentMeasurementStyle(style))
}
}
// MARK: - Key
fileprivate extension EquipmentMeasurement.FlaggedMeasurement {
// 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<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