hi, so I have 3 files in my xcode:
ContentView
import SwiftUI
struct ContentView: View {
@State private var email = ""
@State private var password = ""
@State private var wrongEmail = 0
@State private var wrongPassword = 0
@State private var showingLoginScreen = false
@State private var userData: User? // Declare a @State property for UserData
var body: some View {
NavigationView {
ZStack {
Color.blue
.ignoresSafeArea()
Circle()
.scale(1.7)
.foregroundColor(.white.opacity(0.15))
Circle()
.scale(1.35)
.foregroundColor(.white)
VStack {
Text("Login")
.font(.largeTitle)
.bold().padding()
TextField("Email", text: $email)
.padding()
.frame(width: 300, height: 50)
.background(Color.black.opacity(0.05))
.cornerRadius(10)
.border(.red, width: CGFloat(wrongEmail))
SecureField("Password", text: $password)
.padding()
.frame(width: 300, height: 50)
.background(Color.black.opacity(0.05))
.cornerRadius(10)
.border(.red, width: CGFloat(wrongPassword))
Button("Login") {
authenticateUser(email: email, password: password)
}
.foregroundColor(.white)
.frame(width: 300, height: 50)
.background(Color.blue)
.cornerRadius(10)
NavigationLink(
destination: ArtworkView(user: userData),
isActive: $showingLoginScreen
) {
EmptyView()
}
// NavigationLink(destination: Text("You are logged in @\(email)"), isActive: $showingLoginScreen) {
// EmptyView()
// }
}
}.navigationBarHidden(true)
}
}
func authenticateUser(email: String, password: String) {
guard let url = URL(string: "https://api.hangn.art/api/login") else {
return
}
print("making api call")
var request = URLRequest(url: url)
// method, body, headers
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body: [String: AnyHashable] = [
"email": email,
"password": password
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
//Make the request
let task = URLSession.shared.dataTask(with: request) { data, _, error in
guard let data = data, error == nil else {
return
}
print(String(data: data, encoding: .utf8))
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase // Configure snake case decoding
do {
// let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
let response = try decoder.decode(LoginResponse.self, from: data)
self.userData = response.user
let userData = try decoder.decode(User.self, from: data)
print("SUCCESS: \(userData)")
wrongEmail = 0
wrongPassword = 0
showingLoginScreen = true
}
catch {
print("Error parsing response data: \(error)")
print("Response data: \(String(data: data, encoding: .utf8) ?? "")")
}
}
task.resume()
}
}
//struct Response: Codable {
// let email: String
// let password: String
//}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
ArtworkView
import SwiftUI
struct ArtworkView: View {
var user: User?
var body: some View {
if let user = user {
VStack {
Text("Name: \(user.firstName) \(user.lastName)")
Text("Email: \(user.email)")
Text("Description: \(user.description)")
// ... display other properties ...
}
} else {
Text("Loading...")
}
}
}
User
import Foundation
struct LoginResponse: Decodable {
let token: String
let user: User
}
struct User: Decodable {
let clientId: Int
let createdAt: String
let description: String
let email: String
let emailVerifiedAt: String?
let firstName: String
let id: Int
let image: String
let lastName: String
let location: String? // Make it optional
let pmLastFour: String? // Make it optional
let pmType: String? // Make it optional
let stripeId: String
let trialEndsAt: String? // Make it optional
let updatedAt: String
// Define custom keys for snake case properties
private enum CodingKeys: String, CodingKey {
case clientId = "client_id"
case createdAt = "created_at"
case emailVerifiedAt = "email_verified_at"
case firstName = "first_name"
case lastName = "last_name"
case pmLastFour = "pm_last_four"
case pmType = "pm_type"
case stripeId = "stripe_id"
case trialEndsAt = "trial_ends_at"
// ... other properties ...
}
}
why am I getting: Type 'User' does not conform to protocol 'Decodable'