Files
swift-composable-architectu…/Examples/TicTacToe/tic-tac-toe/Sources/TwoFactorSwiftUI/TwoFactorView.swift
Stephen Celis 87f388bedb Further Modernize Demos (#914)
* Modernize Demos

* wip
2021-12-09 22:41:58 -05:00

107 lines
2.8 KiB
Swift

import AuthenticationClient
import ComposableArchitecture
import SwiftUI
import TwoFactorCore
public struct TwoFactorView: View {
let store: Store<TwoFactorState, TwoFactorAction>
struct ViewState: Equatable {
var alert: AlertState<TwoFactorAction>?
var code: String
var isActivityIndicatorVisible: Bool
var isFormDisabled: Bool
var isSubmitButtonDisabled: Bool
init(state: TwoFactorState) {
self.alert = state.alert
self.code = state.code
self.isActivityIndicatorVisible = state.isTwoFactorRequestInFlight
self.isFormDisabled = state.isTwoFactorRequestInFlight
self.isSubmitButtonDisabled = !state.isFormValid
}
}
enum ViewAction: Equatable {
case alertDismissed
case codeChanged(String)
case submitButtonTapped
}
public init(store: Store<TwoFactorState, TwoFactorAction>) {
self.store = store
}
public var body: some View {
WithViewStore(
self.store.scope(state: ViewState.init, action: TwoFactorAction.init)
) { viewStore in
ScrollView {
VStack(spacing: 16) {
Text(#"To confirm the second factor enter "1234" into the form."#)
VStack(alignment: .leading) {
Text("Code")
TextField(
"1234",
text: viewStore.binding(get: \.code, send: ViewAction.codeChanged)
)
.keyboardType(.numberPad)
.textFieldStyle(.roundedBorder)
}
HStack {
Button("Submit") {
viewStore.send(.submitButtonTapped)
}
.disabled(viewStore.isSubmitButtonDisabled)
if viewStore.isActivityIndicatorVisible {
ProgressView()
}
}
}
.alert(self.store.scope(state: \.alert), dismiss: .alertDismissed)
.disabled(viewStore.isFormDisabled)
.padding(.horizontal)
}
}
.navigationBarTitle("Confirmation Code")
}
}
extension TwoFactorAction {
init(action: TwoFactorView.ViewAction) {
switch action {
case .alertDismissed:
self = .alertDismissed
case let .codeChanged(code):
self = .codeChanged(code)
case .submitButtonTapped:
self = .submitButtonTapped
}
}
}
struct TwoFactorView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
TwoFactorView(
store: Store(
initialState: TwoFactorState(token: "deadbeef"),
reducer: twoFactorReducer,
environment: TwoFactorEnvironment(
authenticationClient: AuthenticationClient(
login: { _ in Effect(value: .init(token: "deadbeef", twoFactorRequired: false)) },
twoFactor: { _ in
Effect(value: .init(token: "deadbeef", twoFactorRequired: false))
}
),
mainQueue: .main
)
)
)
}
}
}