import Foundation import ManaCore import Observation /// State-Maschine für ``ManaResetPasswordView``. Wraps /// `AuthClient.resetPassword`. Wird aus dem Universal-Link-Handler /// der App aufgerufen mit dem Token aus dem `?token=…`-Query-Param. @MainActor @Observable public final class ResetPasswordViewModel { public enum Status: Equatable, Sendable { case idle case submitting case done case error(String) } public let token: String public var newPassword: String = "" public var confirmPassword: String = "" public private(set) var status: Status = .idle private let auth: AuthClient public init(token: String, auth: AuthClient) { self.token = token self.auth = auth } public var canSubmit: Bool { guard !newPassword.isEmpty, !confirmPassword.isEmpty else { return false } guard newPassword == confirmPassword else { return false } guard newPassword.count >= 8 else { return false } if case .submitting = status { return false } return true } public var isSubmitting: Bool { if case .submitting = status { return true } return false } /// UI-Hint je nach Eingabe-Status. Nil = alles ok oder noch leer. public var validationHint: String? { if !newPassword.isEmpty, newPassword.count < 8 { return "Passwort muss mindestens 8 Zeichen lang sein." } if !confirmPassword.isEmpty, newPassword != confirmPassword { return "Die Passwörter stimmen nicht überein." } return nil } public func submit() async { guard canSubmit else { return } status = .submitting do { try await auth.resetPassword(token: token, newPassword: newPassword) newPassword = "" confirmPassword = "" status = .done } catch let error as AuthError { status = .error(error.errorDescription ?? "Reset fehlgeschlagen") } catch { status = .error(String(describing: error)) } } }