import ManaCore import SwiftUI /// Vollständiger Login-Screen: Email + Passwort + Primary-Submit /// + Sekundär-Buttons "Konto erstellen" und "Passwort vergessen". /// /// Bei `.emailNotVerified` schaltet die View automatisch auf /// ``ManaEmailVerifyGateView`` um — der User kann von dort die /// Verify-Mail erneut anfordern. /// /// Apps binden ein: /// ```swift /// ManaLoginView( /// auth: authClient, /// onSignUpTapped: { presentingSignUp = true }, /// onForgotTapped: { presentingForgot = true } /// ) /// .manaBrand(.cardecky) /// ``` public struct ManaLoginView: View { @Environment(\.manaBrand) private var brand @State private var model: LoginViewModel private let auth: AuthClient private let onSignUpTapped: () -> Void private let onForgotTapped: () -> Void /// - Parameters: /// - auth: gemeinsamer `AuthClient` der App. /// - onSignUpTapped: präsentiert ``ManaSignUpView`` (Sheet, /// Push, Navigation — die App entscheidet). /// - onForgotTapped: präsentiert ``ManaForgotPasswordView``. public init( auth: AuthClient, onSignUpTapped: @escaping () -> Void, onForgotTapped: @escaping () -> Void ) { self.auth = auth _model = State(initialValue: LoginViewModel(auth: auth)) self.onSignUpTapped = onSignUpTapped self.onForgotTapped = onForgotTapped } public var body: some View { switch model.status { case let .emailNotVerified(email): ManaEmailVerifyGateView( email: email, auth: auth, onBackToLogin: { model.resetToIdle() } ) default: loginForm } } @ViewBuilder private var loginForm: some View { ManaAuthScaffold { VStack(spacing: 16) { ManaTextField("Email", text: $model.email) .manaEmailField() ManaSecureField("Passwort", text: $model.password, textContentType: .password) ManaPrimaryButton( "Anmelden", isLoading: model.isSigningIn, isEnabled: model.canSubmit ) { Task { await model.submit() } } if case let .error(message) = model.status { Text(message) .font(.footnote) .foregroundStyle(brand.error) .multilineTextAlignment(.center) .padding(.top, 4) } } .padding(.top, 16) VStack(spacing: 12) { Button("Konto erstellen", action: onSignUpTapped) .font(.subheadline) .foregroundStyle(brand.primary) Button("Passwort vergessen?", action: onForgotTapped) .font(.subheadline) .foregroundStyle(brand.mutedForeground) } .padding(.top, 8) } } }