110 lines
3.7 KiB
Swift
110 lines
3.7 KiB
Swift
import SwiftUI
|
|
|
|
/// "Anmelden" screen — the default screen of `AuthFlowView`. Talks to auth
|
|
/// state exclusively through `AppState.login(email:password:)`; never calls
|
|
/// `AuthAPI` directly (see `AppState`'s own doc comment for why).
|
|
struct LoginView: View {
|
|
@EnvironmentObject private var appState: AppState
|
|
|
|
/// Switches `AuthFlowView` to the signup screen.
|
|
var onSwitchToSignup: () -> Void
|
|
|
|
@State private var email = ""
|
|
@State private var password = ""
|
|
@State private var isSubmitting = false
|
|
|
|
private var canSubmit: Bool {
|
|
!email.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
&& !password.isEmpty
|
|
&& !isSubmitting
|
|
}
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: ZenithSpacing.md) {
|
|
VStack(spacing: ZenithSpacing.xs) {
|
|
Image(systemName: "doc.text.viewfinder")
|
|
.font(.system(size: 40))
|
|
.foregroundStyle(Color.zenithBlack)
|
|
Text("ScanReceipts")
|
|
.zenithHeadlineLgStyle()
|
|
}
|
|
.padding(.top, ZenithSpacing.lg)
|
|
|
|
VStack(spacing: ZenithSpacing.sm) {
|
|
ZenithTextField(
|
|
label: "E-Mail",
|
|
text: $email,
|
|
keyboardType: .emailAddress,
|
|
textContentType: .username,
|
|
autocapitalization: .never,
|
|
autocorrectionDisabled: true
|
|
)
|
|
|
|
ZenithTextField(
|
|
label: "Passwort",
|
|
text: $password,
|
|
isSecure: true,
|
|
textContentType: .password
|
|
)
|
|
}
|
|
|
|
if let error = appState.lastError {
|
|
Text(error)
|
|
.zenithBodySmStyle(color: .zenithError)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
|
|
Button {
|
|
Task { await submit() }
|
|
} label: {
|
|
Group {
|
|
if isSubmitting {
|
|
ProgressView()
|
|
.tint(.white)
|
|
} else {
|
|
Text("Anmelden")
|
|
}
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.zenithPrimary)
|
|
.disabled(!canSubmit)
|
|
|
|
HStack(spacing: ZenithSpacing.sm) {
|
|
ZenithDivider()
|
|
Text("oder")
|
|
.zenithBodySmStyle()
|
|
ZenithDivider()
|
|
}
|
|
|
|
// No outer `.frame(height:)` here — AppleSignInButton sizes
|
|
// its own button (minHeight: 50) and needs the flexibility
|
|
// to grow when it shows its own inline error text below it.
|
|
AppleSignInButton()
|
|
|
|
Button("Noch kein Konto? Registrieren") {
|
|
appState.lastError = nil
|
|
onSwitchToSignup()
|
|
}
|
|
.buttonStyle(.zenithPlain)
|
|
.padding(.top, ZenithSpacing.xs)
|
|
}
|
|
.padding(.horizontal, ZenithSpacing.md)
|
|
.padding(.bottom, ZenithSpacing.lg)
|
|
}
|
|
.scrollDismissesKeyboard(.interactively)
|
|
.background(Color.zenithBg)
|
|
}
|
|
|
|
private func submit() async {
|
|
guard canSubmit else { return }
|
|
isSubmitting = true
|
|
defer { isSubmitting = false }
|
|
await appState.login(
|
|
email: email.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
password: password
|
|
)
|
|
}
|
|
}
|