import ManaCore import SwiftUI /// Sign-Up-Screen: Email + Name (optional) + Passwort. Bei Erfolg /// und `requireEmailVerification: true` (Default) zeigt der View /// den Hinweis-Screen mit Resend-Mail-Button — sobald die Mail /// geklickt wurde, schließt die App den Sheet/Push manuell oder /// reagiert auf den nächsten `signIn`-Versuch. /// /// Apps binden ein: /// ```swift /// ManaSignUpView( /// auth: authClient, /// sourceAppUrl: URL(string: "https://cardecky.mana.how/auth/verify"), /// onDone: { dismissSignUpSheet() } /// ) /// ``` public struct ManaSignUpView: View { @Environment(\.manaBrand) private var brand @State private var model: SignUpViewModel private let auth: AuthClient private let onDone: () -> Void /// - Parameters: /// - auth: gemeinsamer `AuthClient` der App. /// - sourceAppUrl: Universal-Link der App für den Verify-Klick- /// Redirect (z.B. `https://cardecky.mana.how/auth/verify`). /// - onDone: Callback wenn der User "Fertig" auf dem Hinweis- /// Screen drückt oder direkt eingeloggt ist. Apps schließen /// hier das Sheet. public init( auth: AuthClient, sourceAppUrl: URL? = nil, onDone: @escaping () -> Void ) { self.auth = auth _model = State(initialValue: SignUpViewModel(auth: auth, sourceAppUrl: sourceAppUrl)) self.onDone = onDone } public var body: some View { switch model.status { case let .awaitingVerification(email): awaitingVerificationView(email: email) case .signedIn: // Server hat direkt Tokens geliefert — UI muss nichts mehr // tun, App soll den Sheet schließen. ManaAuthScaffold(showsHeader: false) { ProgressView() .onAppear { onDone() } } default: signUpForm } } @ViewBuilder private var signUpForm: some View { ManaAuthScaffold { VStack(spacing: 16) { Text("Konto erstellen") .font(.title2) .fontWeight(.semibold) .foregroundStyle(brand.foreground) .frame(maxWidth: .infinity, alignment: .leading) ManaTextField("Email", text: $model.email) .manaEmailField() ManaTextField("Name (optional)", text: $model.name) .textContentType(.name) ManaSecureField( "Passwort", text: $model.password, textContentType: .newPassword ) if let hint = model.passwordHint { Text(hint) .font(.footnote) .foregroundStyle(brand.mutedForeground) .frame(maxWidth: .infinity, alignment: .leading) } ManaPrimaryButton( "Registrieren", isLoading: model.isRegistering, 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) Button("Abbrechen", action: onDone) .font(.subheadline) .foregroundStyle(brand.mutedForeground) .padding(.top, 12) } } @ViewBuilder private func awaitingVerificationView(email: String) -> some View { ManaAuthScaffold { VStack(spacing: 16) { Image(systemName: "checkmark.circle.fill") .font(.system(size: 56, weight: .light)) .foregroundStyle(brand.success) Text("Fast geschafft!") .font(.title2) .fontWeight(.semibold) .foregroundStyle(brand.foreground) Text( "Wir haben eine Bestätigungs-Mail an **\(email)** geschickt. " + "Klicke den Link in der Mail, dann kannst du dich anmelden." ) .font(.subheadline) .foregroundStyle(brand.mutedForeground) .multilineTextAlignment(.center) ManaPrimaryButton("Fertig") { onDone() } .padding(.top, 16) } } } }