import ManaCore import SwiftUI /// "Neues Passwort setzen"-Screen. Wird aus dem Universal-Link-Handler /// der App aufgerufen, sobald der User den Reset-Link aus der Email /// geklickt hat — die App extrahiert `?token=…` aus der URL und /// präsentiert diesen View. /// /// ```swift /// // In App.handleUniversalLink: /// if url.path == "/auth/reset", let token = url.queryToken { /// showResetPasswordSheet(token: token) /// } /// ``` public struct ManaResetPasswordView: View { @Environment(\.manaBrand) private var brand @State private var model: ResetPasswordViewModel private let onDone: () -> Void /// - Parameters: /// - token: Reset-Token aus der Email (`?token=…`). /// - auth: gemeinsamer `AuthClient` der App. /// - onDone: Callback bei Erfolg oder Abbruch — App schließt /// den Sheet und navigiert zurück zum Login. public init( token: String, auth: AuthClient, onDone: @escaping () -> Void ) { _model = State(initialValue: ResetPasswordViewModel(token: token, auth: auth)) self.onDone = onDone } public var body: some View { switch model.status { case .done: doneView default: formView } } @ViewBuilder private var formView: some View { ManaAuthScaffold { VStack(spacing: 16) { Text("Neues Passwort") .font(.title2) .fontWeight(.semibold) .foregroundStyle(brand.foreground) .frame(maxWidth: .infinity, alignment: .leading) Text("Wähle ein neues Passwort. Mindestens 8 Zeichen.") .font(.subheadline) .foregroundStyle(brand.mutedForeground) .frame(maxWidth: .infinity, alignment: .leading) ManaSecureField( "Neues Passwort", text: $model.newPassword, textContentType: .newPassword ) ManaSecureField( "Passwort bestätigen", text: $model.confirmPassword, textContentType: .newPassword ) if let hint = model.validationHint { Text(hint) .font(.footnote) .foregroundStyle(brand.mutedForeground) .frame(maxWidth: .infinity, alignment: .leading) } ManaPrimaryButton( "Passwort setzen", isLoading: model.isSubmitting, 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 var doneView: some View { ManaAuthScaffold { VStack(spacing: 16) { Image(systemName: "lock.open.fill") .font(.system(size: 56, weight: .light)) .foregroundStyle(brand.success) Text("Passwort aktualisiert") .font(.title2) .fontWeight(.semibold) .foregroundStyle(brand.foreground) Text("Du kannst dich jetzt mit deinem neuen Passwort anmelden.") .font(.subheadline) .foregroundStyle(brand.mutedForeground) .multilineTextAlignment(.center) ManaPrimaryButton("Zum Login") { onDone() } .padding(.top, 16) } } } }