Files
platform/ios/Platform 1.44.16 AM/Platform/Features/Auth/LoginView.swift
Yusuf Suleman fdb8aeba8a
All checks were successful
Security Checks / dependency-audit (push) Successful in 12s
Security Checks / secret-scanning (push) Successful in 3s
Security Checks / dockerfile-lint (push) Successful in 3s
restore: original UI views from first build, keep fixed models/API
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 01:54:46 -05:00

159 lines
6.1 KiB
Swift

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
}
}
}