restore: original UI views from first build, keep fixed models/API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
158
ios/Platform 1.44.16 AM/Platform/Features/Auth/LoginView.swift
Normal file
158
ios/Platform 1.44.16 AM/Platform/Features/Auth/LoginView.swift
Normal file
@@ -0,0 +1,158 @@
|
||||
import SwiftUI
|
||||
|
||||
struct LoginView: View {
|
||||
@Environment(AuthManager.self) private var authManager
|
||||
|
||||
@State private var username = ""
|
||||
@State private var password = ""
|
||||
@State private var isLoading = false
|
||||
@FocusState private var focusedField: Field?
|
||||
|
||||
private enum Field: Hashable {
|
||||
case username, password
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color.canvas
|
||||
.ignoresSafeArea()
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: 32) {
|
||||
Spacer()
|
||||
.frame(height: 60)
|
||||
|
||||
// Logo / Branding
|
||||
VStack(spacing: 8) {
|
||||
Image(systemName: "square.grid.2x2.fill")
|
||||
.font(.system(size: 48))
|
||||
.foregroundStyle(Color.accentWarm)
|
||||
|
||||
Text("Platform")
|
||||
.font(.largeTitle.weight(.bold))
|
||||
.foregroundStyle(Color.text1)
|
||||
|
||||
Text("Sign in to your dashboard")
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Color.text3)
|
||||
}
|
||||
|
||||
// Form
|
||||
VStack(spacing: 16) {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Username")
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundStyle(Color.text3)
|
||||
.textCase(.uppercase)
|
||||
|
||||
TextField("Enter username", text: $username)
|
||||
.textFieldStyle(.plain)
|
||||
.textContentType(.username)
|
||||
.textInputAutocapitalization(.never)
|
||||
.autocorrectionDisabled()
|
||||
.focused($focusedField, equals: .username)
|
||||
.padding(14)
|
||||
.background(Color.surface)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.stroke(
|
||||
focusedField == .username ? Color.accentWarm : Color.black.opacity(0.06),
|
||||
lineWidth: focusedField == .username ? 2 : 1
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
Text("Password")
|
||||
.font(.caption.weight(.semibold))
|
||||
.foregroundStyle(Color.text3)
|
||||
.textCase(.uppercase)
|
||||
|
||||
SecureField("Enter password", text: $password)
|
||||
.textFieldStyle(.plain)
|
||||
.textContentType(.password)
|
||||
.focused($focusedField, equals: .password)
|
||||
.padding(14)
|
||||
.background(Color.surface)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.stroke(
|
||||
focusedField == .password ? Color.accentWarm : Color.black.opacity(0.06),
|
||||
lineWidth: focusedField == .password ? 2 : 1
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if let error = authManager.loginError {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "exclamationmark.circle.fill")
|
||||
.foregroundStyle(Color.error)
|
||||
Text(error)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(Color.error)
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(.top, 4)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
|
||||
// Sign In Button
|
||||
Button {
|
||||
performLogin()
|
||||
} label: {
|
||||
HStack(spacing: 8) {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
.controlSize(.small)
|
||||
.tint(.white)
|
||||
}
|
||||
Text("Sign In")
|
||||
.font(.body.weight(.semibold))
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 16)
|
||||
.background(canSubmit ? Color.accentWarm : Color.text4)
|
||||
.foregroundStyle(.white)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 14))
|
||||
}
|
||||
.disabled(!canSubmit)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal, 28)
|
||||
}
|
||||
}
|
||||
.onSubmit {
|
||||
switch focusedField {
|
||||
case .username:
|
||||
focusedField = .password
|
||||
case .password:
|
||||
performLogin()
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var canSubmit: Bool {
|
||||
!username.trimmingCharacters(in: .whitespaces).isEmpty
|
||||
&& !password.isEmpty
|
||||
&& !isLoading
|
||||
}
|
||||
|
||||
private func performLogin() {
|
||||
guard canSubmit else { return }
|
||||
isLoading = true
|
||||
focusedField = nil
|
||||
Task {
|
||||
await authManager.login(
|
||||
username: username.trimmingCharacters(in: .whitespaces),
|
||||
password: password
|
||||
)
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user