This commit is contained in:
Trey t
2025-11-05 20:31:01 -06:00
parent fe99f67f81
commit bc289d6c88
17 changed files with 819 additions and 203 deletions

View File

@@ -1,9 +1,11 @@
import SwiftUI
import ComposeApp
struct RegisterView: View {
@StateObject private var viewModel = RegisterViewModel()
@Environment(\.dismiss) var dismiss
@FocusState private var focusedField: Field?
@State private var showVerifyEmail = false
enum Field {
case username, email, password, confirmPassword
@@ -11,114 +13,99 @@ struct RegisterView: View {
var body: some View {
NavigationView {
ZStack {
Color(.systemGroupedBackground)
.ignoresSafeArea()
Form {
Section {
VStack(spacing: 16) {
Image(systemName: "person.badge.plus")
.font(.system(size: 60))
.foregroundStyle(.blue.gradient)
ScrollView {
VStack(spacing: 24) {
// Icon and Title
RegisterHeader()
Text("Join MyCrib")
.font(.largeTitle)
.fontWeight(.bold)
// Registration Form
VStack(spacing: 16) {
// Username Field
VStack(alignment: .leading, spacing: 8) {
Text("Username")
.font(.subheadline)
.foregroundColor(.secondary)
TextField("Enter your username", text: $viewModel.username)
.textFieldStyle(.roundedBorder)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.focused($focusedField, equals: .username)
.submitLabel(.next)
.onSubmit {
focusedField = .email
}
}
// Email Field
VStack(alignment: .leading, spacing: 8) {
Text("Email")
.font(.subheadline)
.foregroundColor(.secondary)
TextField("Enter your email", text: $viewModel.email)
.textFieldStyle(.roundedBorder)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.keyboardType(.emailAddress)
.focused($focusedField, equals: .email)
.submitLabel(.next)
.onSubmit {
focusedField = .password
}
}
// Password Field
VStack(alignment: .leading, spacing: 8) {
Text("Password")
.font(.subheadline)
.foregroundColor(.secondary)
SecureField("Enter your password", text: $viewModel.password)
.textFieldStyle(.roundedBorder)
.focused($focusedField, equals: .password)
.submitLabel(.next)
.onSubmit {
focusedField = .confirmPassword
}
}
// Confirm Password Field
VStack(alignment: .leading, spacing: 8) {
Text("Confirm Password")
.font(.subheadline)
.foregroundColor(.secondary)
SecureField("Confirm your password", text: $viewModel.confirmPassword)
.textFieldStyle(.roundedBorder)
.focused($focusedField, equals: .confirmPassword)
.submitLabel(.go)
.onSubmit {
viewModel.register()
}
}
// Error Message
if let errorMessage = viewModel.errorMessage {
ErrorMessageView(message: errorMessage, onDismiss: viewModel.clearError)
}
// Register Button
Button(action: viewModel.register) {
HStack {
if viewModel.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .white))
} else {
Text("Create Account")
.fontWeight(.semibold)
}
}
.frame(maxWidth: .infinity)
.padding()
.background(viewModel.isLoading ? Color.gray : Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.disabled(viewModel.isLoading)
}
.padding(.horizontal, 24)
Spacer()
Text("Start managing your properties today")
.font(.subheadline)
.foregroundColor(.secondary)
}
.frame(maxWidth: .infinity)
.padding(.vertical)
}
.listRowBackground(Color.clear)
Section {
TextField("Username", text: $viewModel.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.focused($focusedField, equals: .username)
.submitLabel(.next)
.onSubmit {
focusedField = .email
}
TextField("Email", text: $viewModel.email)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.keyboardType(.emailAddress)
.focused($focusedField, equals: .email)
.submitLabel(.next)
.onSubmit {
focusedField = .password
}
} header: {
Text("Account Information")
}
Section {
SecureField("Password", text: $viewModel.password)
.focused($focusedField, equals: .password)
.submitLabel(.next)
.onSubmit {
focusedField = .confirmPassword
}
SecureField("Confirm Password", text: $viewModel.confirmPassword)
.focused($focusedField, equals: .confirmPassword)
.submitLabel(.go)
.onSubmit {
viewModel.register()
}
} header: {
Text("Security")
} footer: {
Text("Password must be secure")
}
if let errorMessage = viewModel.errorMessage {
Section {
HStack {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(.red)
Text(errorMessage)
.foregroundColor(.red)
.font(.subheadline)
}
}
}
Section {
Button(action: viewModel.register) {
HStack {
Spacer()
if viewModel.isLoading {
ProgressView()
} else {
Text("Create Account")
.fontWeight(.semibold)
}
Spacer()
}
}
.disabled(viewModel.isLoading)
}
}
.navigationTitle("Create Account")
.navigationBarTitleDisplayMode(.inline)
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
@@ -127,7 +114,18 @@ struct RegisterView: View {
}
}
.fullScreenCover(isPresented: $viewModel.isRegistered) {
MainTabView()
VerifyEmailView(
onVerifySuccess: {
dismiss()
showVerifyEmail = false
},
onLogout: {
// Logout and return to login screen
TokenManager().clearToken()
LookupsManager.shared.clear()
dismiss()
}
)
}
}
}