Feat: Working on pressure estimations feature

This commit is contained in:
2024-06-04 15:16:12 -04:00
parent e70f554b07
commit aa40985486
5 changed files with 153 additions and 52 deletions

View File

@@ -59,7 +59,8 @@ let package = Package(
.target(
name: "Styleguide",
dependencies: [
"SharedModels"
"SharedModels",
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
.testTarget(

View File

@@ -6,22 +6,39 @@ import SwiftUI
@Reducer
public struct EstimateSettingsForm {
@CasePathable
public enum InfoView {
case budgets
case updatedAirflow
}
@Reducer(state: .equatable)
public enum Destination {
case infoView(InfoViewFeature)
}
@ObservableState
public struct State: Equatable {
@Presents public var destination: Destination.State?
public var budgets: BudgetedPercentEnvelope
public let equipmentType: EquipmentType
public let equipmentMeasurement: EquipmentMeasurement
public var fanType: FanType
public var focusedField: Field? = nil
public var updatedAirflow: Double?
public init(
equipmentType: EquipmentType,
destination: Destination.State? = nil,
equipmentMeasurement: EquipmentMeasurement,
fanType: FanType = .constantSpeed,
updatedAirflow: Double? = nil
) {
self.budgets = .init(equipmentType: equipmentType, fanType: fanType)
self.equipmentType = equipmentType
self.destination = destination
self.equipmentMeasurement = equipmentMeasurement
self.budgets = .init(
equipmentType: equipmentMeasurement.equipmentType,
fanType: fanType
)
self.fanType = fanType
self.updatedAirflow = updatedAirflow
}
@@ -42,19 +59,15 @@ public struct EstimateSettingsForm {
public enum Action: BindableAction, ViewAction {
case binding(BindingAction<State>)
case destination(PresentationAction<Destination.Action>)
case view(View)
@CasePathable
public enum View {
case infoButtonTapped(InfoButton)
case infoButtonTapped(InfoView)
case nextButtonTapped
case resetButtonTapped
case submitField
@CasePathable
public enum InfoButton {
case budgets
case updatedAirflow
}
}
}
@@ -62,9 +75,10 @@ public struct EstimateSettingsForm {
BindingReducer()
Reduce<State, Action> { state, action in
switch action {
case .binding(\.fanType):
state.budgets = .init(
equipmentType: state.equipmentType,
equipmentType: state.equipmentMeasurement.equipmentType,
fanType: state.fanType
)
return .none
@@ -72,15 +86,29 @@ public struct EstimateSettingsForm {
case .binding:
return .none
case .destination(.dismiss):
state.destination = nil
return .none
case .destination:
return .none
case let .view(action):
switch action {
case .infoButtonTapped:
case let .infoButtonTapped(infoView):
state.destination = .infoView(.init(view: infoView))
return .none
case .nextButtonTapped:
#warning("Fix me.")
return .none
case .resetButtonTapped:
state.budgets = .init(equipmentType: state.equipmentType, fanType: state.fanType)
state.budgets = .init(
equipmentType: state.equipmentMeasurement.equipmentType,
fanType: state.fanType
)
state.updatedAirflow = nil
return .none
@@ -91,6 +119,7 @@ public struct EstimateSettingsForm {
}
}
}
.ifLet(\.$destination, action: \.destination)
}
}
@@ -121,7 +150,7 @@ public struct EstimateSettingsFormView: View {
Section {
Grid(alignment: .leading, horizontalSpacing: 40) {
if store.equipmentType == .furnaceAndCoil {
if store.equipmentMeasurement.equipmentType == .furnaceAndCoil {
GridRow {
TextLabel("Coil")
percentField("Coil Budget", value: $store.budgets.coilBudget.fraction)
@@ -177,7 +206,11 @@ public struct EstimateSettingsFormView: View {
}
Section {
TextField(
"Airflow",
value: $store.updatedAirflow,
fractionLength: 0
)
} header: {
HStack {
Text("Updated Airflow")
@@ -189,8 +222,9 @@ public struct EstimateSettingsFormView: View {
ResetButton { send(.resetButtonTapped) }
Spacer()
Button("Next") {
#warning("Fix me.")
send(.nextButtonTapped)
}
.disabled(!store.isValid)
}
.padding(.top)
}
@@ -198,6 +232,16 @@ public struct EstimateSettingsFormView: View {
.labelsHidden()
.bind($focusedField, to: $store.focusedField)
.navigationTitle("Estimate Settings")
.sheet(
item: $store.scope(
state: \.destination?.infoView,
action: \.destination.infoView
)
) { store in
NavigationStack {
InfoView(store: store)
}
}
}
private func percentField(
@@ -219,11 +263,36 @@ fileprivate struct BudgetFlagViewStyle: FlaggedViewStyle {
}
}
fileprivate extension InfoViewFeature.State {
init(view: EstimateSettingsForm.InfoView) {
switch view {
case .budgets:
self.init(
title: "Budgets",
body: """
Budgeted percentages for static pressure estimations, these generally are set to
reasonable defaults, however you can change them if desired.
Note: These must total up to 100%.
"""
)
case .updatedAirflow:
self.init(
title: "Updated Airflow",
body: """
This is used to generated estimated static pressures at the updated airflow
compared to the existing airflow of the system.
"""
)
}
}
}
#Preview {
NavigationStack {
EstimateSettingsFormView(
store: Store(
initialState: EstimateSettingsForm.State(equipmentType: .furnaceAndCoil)
initialState: EstimateSettingsForm.State(equipmentMeasurement: .furnaceAndCoil(.init()))
) {
EstimateSettingsForm()
}

View File

@@ -14,7 +14,11 @@ public struct InfoButton: View {
Button(action: action) {
Label("Info", systemImage: "info.circle")
}
.buttonStyle(infoButtonStyle)
.buttonStyle(.plain)
.labelStyle(.iconOnly)
.font(.title2)
.foregroundStyle(Color.accentColor)
// .buttonStyle(infoButtonStyle)
}
}

View File

@@ -1,48 +1,74 @@
import ComposableArchitecture
import SwiftUI
public struct InfoView: View {
let headingText: String
@Reducer
public struct InfoViewFeature {
public init() { }
@ObservableState
public struct State: Equatable {
let titleText: String
let bodyText: String
public init(heading headingText: String, body bodyText: String) {
self.headingText = headingText
public init(
title titleText: String,
body bodyText: String
) {
self.titleText = titleText
self.bodyText = bodyText
}
}
public enum Action {
case dismissButtonTapped
}
@Dependency(\.dismiss) var dismiss
public var body: some ReducerOf<Self> {
Reduce { _, action in
switch action {
case .dismissButtonTapped:
return .run { _ in await self.dismiss() }
}
}
}
}
public struct InfoView: View {
let store: StoreOf<InfoViewFeature>
public init(store: StoreOf<InfoViewFeature>) {
self.store = store
}
public var body: some View {
VStack(spacing: 40) {
ZStack {
Text(headingText)
.font(.headline)
.bold()
.foregroundStyle(Color.white)
.padding()
}
.background {
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(Color.orange.opacity(0.6))
}
ZStack {
Text(bodyText)
Text(store.bodyText)
.font(.callout)
.padding()
}
.background {
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(Color.secondary.opacity(0.3))
}
.padding(.horizontal, 10)
Spacer()
}
.navigationTitle(store.titleText)
.padding(.horizontal)
.navigationBarBackButtonHidden()
.toolbar {
Button("Done") {
store.send(.dismissButtonTapped)
}
}
}
}
#Preview {
InfoView(heading: "Generic Info View", body: "Explain what this view does here...")
InfoView(
store: Store(
initialState: InfoViewFeature.State(
title: "Generic Info View",
body: "Explain what this view does here..."
),
reducer: InfoViewFeature.init
)
)
}

View File

@@ -22,6 +22,7 @@ public struct DefaultInfoButtonStyle: PrimitiveButtonStyle {
public func makeBody(configuration: Configuration) -> some View {
configuration.label
.buttonStyle(.plain)
.font(.title2)
.foregroundStyle(Color.accentColor)
.labelStyle(.iconOnly)
}