import ComposableArchitecture import DependenciesAdditions import SharedModels import Styleguide import SwiftUI import TCAExtras #warning("Fix shared settings.") @Reducer public struct PressureEstimationsFeature { public init() { } @Reducer(state: .equatable) public enum Destination { case equipmentMeasurements(EquipmentMeasurementForm) } @ObservableState public struct State: Equatable { @Presents public var destination: Destination.State? @Shared(.sharedPressureEstimationSettings) var sharedSettings = SharedPressureEstimationState() public var equipmentSettings: EquipmentSettingsForm.State public init( destination: Destination.State? = nil, sharedSettings: SharedPressureEstimationState = .init() ) { self.destination = destination self._sharedSettings = Shared(sharedSettings) self._equipmentSettings = .init(sharedSettings: self._sharedSettings) } } public enum Action: ViewAction { case destination(PresentationAction) case equipmentSettings(EquipmentSettingsForm.Action) case view(View) @CasePathable public enum View { case nextButtonTapped } } @Dependency(\.logger["\(Self.self)"]) var logger public var body: some Reducer { Scope(state: \.equipmentSettings, action: \.equipmentSettings) { EquipmentSettingsForm() } Reduce { state, action in switch action { case .destination: return .none case .equipmentSettings: return .none case let .view(action): switch action { case .nextButtonTapped: return handleNextButtonTapped(&state) } } } .ifLet(\.$destination, action: \.destination) } private func handleNextButtonTapped(_ state: inout State) -> Effect { guard state.destination == nil else { return .fail( """ Received next button tapped action on equipment settings form, but the destination is not nil. This is considered an application logic error. """, logger: logger ) } guard state.equipmentSettings.isValid else { return .fail( """ Received next button tapped action on equipment settings form, but the form is invalid. This is considered an application logic error. """, logger: logger ) } state.destination = .equipmentMeasurements(.init( allowEquipmentTypeSelection: false, sharedSettings: state.$sharedSettings, equipmentType: state.equipmentSettings.equipmentType )) return .none } } @ViewAction(for: PressureEstimationsFeature.self) public struct PressureEstimationsView: View { @Bindable public var store: StoreOf public init(store: StoreOf) { self.store = store } public var body: some View { EquipmentSettingsFormView( store: store.scope(state: \.equipmentSettings, action: \.equipmentSettings) ) .navigationTitle("Equipment Settings") .toolbar { NextButton { send(.nextButtonTapped) } .nextButtonStyle(.toolbar) .disabled(!store.equipmentSettings.isValid) } .navigationDestination( item: $store.scope( state: \.destination?.equipmentMeasurements, action: \.destination.equipmentMeasurements ) ) { measurementStore in EquipmentMeasurementFormView(store: measurementStore) .navigationTitle("Existing Measurements") } } } #Preview { NavigationStack { PressureEstimationsView( store: Store(initialState: PressureEstimationsFeature.State()) { PressureEstimationsFeature()._printChanges() } ) } }