mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-24 12:14:25 +01:00
tic-tac-toe package (#684)
* tic-tac-toe package * Update Package.swift * Tests * wip * wip * wip * Update Package.swift
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
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(RoundedBorderTextFieldStyle())
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user