import SwiftUI struct LoginSheet: View { @EnvironmentObject var appState: AppState @Environment(\.dismiss) private var dismiss @State private var email = "" @State private var password = "" @State private var isLoading = false @State private var error: String? var body: some View { NavigationStack { VStack(spacing: 24) { // Logo Image(systemName: "leaf.circle.fill") .font(.system(size: 60)) .foregroundColor(.green) .padding(.top, 40) Text("Welcome Back") .font(.title.bold()) Text("Log in to save favorites and view your scan history.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal) // Form VStack(spacing: 16) { TextField("Email", text: $email) .keyboardType(.emailAddress) .textContentType(.emailAddress) .autocapitalization(.none) .textFieldStyle(.roundedBorder) SecureField("Password", text: $password) .textContentType(.password) .textFieldStyle(.roundedBorder) } .padding(.horizontal, 24) if let error = error { Text(error) .font(.caption) .foregroundColor(.red) } // Login Button Button { login() } label: { if isLoading { ProgressView() .tint(.black) } else { Text("Log In") .font(.headline) } } .foregroundColor(.black) .frame(maxWidth: .infinity) .padding() .background(isValid ? Color.green : Color.gray) .cornerRadius(12) .disabled(!isValid || isLoading) .padding(.horizontal, 24) // Register Link HStack { Text("Don't have an account?") .foregroundColor(.secondary) Button("Sign Up") { dismiss() appState.showRegisterSheet = true } .foregroundColor(.green) } .font(.subheadline) Spacer() } .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { dismiss() } } } } } private var isValid: Bool { !email.isEmpty && email.contains("@") && !password.isEmpty } private func login() { isLoading = true error = nil Task { do { let (profile, token) = try await APIService.shared.login(email: email, password: password) await appState.setAuth(userId: profile.id, token: token, profile: profile) await MainActor.run { dismiss() } } catch { await MainActor.run { self.error = error.localizedDescription isLoading = false } } } } }