Untitled
unknown
swift
4 months ago
6.2 kB
10
No Index
//
// AddUserViewModel.swift
// looploop admin
//
// Created by Florian Lammert on 08.07.25.
//
import Foundation
import FirebaseFunctions
import FirebaseAuth
extension AddUserView {
@Observable
class ViewModel {
var isLoading: Bool = false
var errorMessage: String? = nil
var successMessage: String? = nil
// Account Information
var email = ""
var confirmEmail = ""
var password = ""
var username = ""
var isPremium = false
var isFormDisabled: Bool {
email.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ||
confirmEmail.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ||
password.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ||
isLoading
}
func createUser() {
isLoading = true
errorMessage = nil
successMessage = nil
// Validate inputs
guard validateInputs() else {
isLoading = false
return
}
Task {
do {
// Create Firebase Auth user
let functions = Functions.functions(region: "europe-west3")
let callable = functions.httpsCallable("adminCreateAuthUser")
let data: [String: Any] = [
"email": email.trimmingCharacters(in: .whitespacesAndNewlines),
"password": password
]
let result = try await callable.call(data)
guard let resultData = result.data as? [String: Any],
let success = resultData["success"] as? Bool,
success == true,
let userId = resultData["userId"] as? String,
let userEmail = resultData["email"] as? String
else {
isLoading = false
errorMessage = "Could not create user."
return
}
// Create DBUser with additional information
let newUser = DBUser(
id: userId,
email: userEmail,
username: username.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? nil: username.trimmingCharacters(in: .whitespacesAndNewlines),
photoUrl: nil,
bio: nil,
diet: nil,
excludedIngredients: nil,
allergies: nil,
kitchenEquipment: nil,
excludedCuisines: nil,
savedRecipeIds: nil,
isPremium: isPremium,
createdAt: Date(),
lastLoginAt: nil
)
// Save to Firestore
try await UserManager.shared.createUser(user: newUser)
reset()
isLoading = false
successMessage = "User created successfully."
DispatchQueue.main.asyncAfter(deadline: .now() + 3) { self.successMessage = nil }
} catch {
isLoading = false
errorMessage = "Failed to create user: \(error.localizedDescription)"
}
}
}
private func validateInputs() -> Bool {
// Check if emails match
guard email.trimmingCharacters(in: .whitespacesAndNewlines) == confirmEmail.trimmingCharacters(in: .whitespacesAndNewlines) else {
errorMessage = "Email addresses do not match."
return false
}
// Validate email format
guard isValidEmail(email.trimmingCharacters(in: .whitespacesAndNewlines)) else {
errorMessage = "Please enter a valid email address."
return false
}
// Validate password strength
guard password.count >= 8 else {
errorMessage = "Password must be at least 8 characters long."
return false
}
// Validate username if provided
if !username.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
let trimmedUsername = username.trimmingCharacters(in: .whitespacesAndNewlines)
guard trimmedUsername.count >= 3 else {
errorMessage = "Username must be at least 3 characters long."
return false
}
guard trimmedUsername.count <= 20 else {
errorMessage = "Username must be no longer than 20 characters."
return false
}
// Check for valid username characters (alphanumeric and underscores)
let usernameRegex = "^[a-zA-Z0-9_]+$"
let usernamePredicate = NSPredicate(format: "SELF MATCHES %@", usernameRegex)
guard usernamePredicate.evaluate(with: trimmedUsername) else {
errorMessage = "Username can only contain letters, numbers, and underscores."
return false
}
}
return true
}
private func isValidEmail(_ email: String) -> Bool {
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailRegex)
return emailPredicate.evaluate(with: email)
}
func reset() {
email = ""
confirmEmail = ""
password = ""
username = ""
isPremium = false
}
}
}
Editor is loading...