Files
honeyDueKMP/iosApp/iosApp/Profile/ProfileView.swift
Trey t a2b81a244b Implement custom 5-color design system across entire iOS app
Apply consistent branding colors (BlueGreen, Cerulean, BrightAmber, PrimaryScarlet,
cream backgrounds) to all screens, components, buttons, icons, and text throughout
the app. Update all Form/List views with proper list row backgrounds to ensure
visual consistency with card-based layouts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 07:58:01 -06:00

156 lines
6.2 KiB
Swift

import SwiftUI
struct ProfileView: View {
@StateObject private var viewModel = ProfileViewModel()
@Environment(\.dismiss) var dismiss
@FocusState private var focusedField: Field?
enum Field {
case firstName, lastName, email
}
var body: some View {
NavigationView {
if viewModel.isLoadingUser {
VStack {
ProgressView()
Text("Loading profile...")
.font(.subheadline)
.foregroundColor(Color.appTextSecondary)
.padding(.top, 8)
}
} else {
Form {
Section {
VStack(spacing: 16) {
Image(systemName: "person.circle.fill")
.font(.system(size: 60))
.foregroundStyle(Color.appPrimary.gradient)
Text("Profile Settings")
.font(.title2)
.fontWeight(.bold)
.foregroundColor(Color.appTextPrimary)
}
.frame(maxWidth: .infinity)
.padding(.vertical)
}
.listRowBackground(Color.clear)
Section {
TextField("First Name", text: $viewModel.firstName)
.textInputAutocapitalization(.words)
.autocorrectionDisabled()
.focused($focusedField, equals: .firstName)
.submitLabel(.next)
.onSubmit {
focusedField = .lastName
}
TextField("Last Name", text: $viewModel.lastName)
.textInputAutocapitalization(.words)
.autocorrectionDisabled()
.focused($focusedField, equals: .lastName)
.submitLabel(.next)
.onSubmit {
focusedField = .email
}
} header: {
Text("Personal Information")
}
.listRowBackground(Color.appBackgroundSecondary)
Section {
TextField("Email", text: $viewModel.email)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
.keyboardType(.emailAddress)
.focused($focusedField, equals: .email)
.submitLabel(.done)
.onSubmit {
viewModel.updateProfile()
}
} header: {
Text("Contact")
} footer: {
Text("Email is required and must be unique")
}
.listRowBackground(Color.appBackgroundSecondary)
if let errorMessage = viewModel.errorMessage {
Section {
HStack {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundColor(Color.appError)
Text(errorMessage)
.foregroundColor(Color.appError)
.font(.subheadline)
}
}
.listRowBackground(Color.appBackgroundSecondary)
}
if let successMessage = viewModel.successMessage {
Section {
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(Color.appPrimary)
Text(successMessage)
.foregroundColor(Color.appPrimary)
.font(.subheadline)
}
}
.listRowBackground(Color.appBackgroundSecondary)
}
Section {
Button(action: viewModel.updateProfile) {
HStack {
Spacer()
if viewModel.isLoading {
ProgressView()
} else {
Text("Save Changes")
.fontWeight(.semibold)
}
Spacer()
}
}
.disabled(viewModel.isLoading || viewModel.email.isEmpty)
}
.listRowBackground(Color.appBackgroundSecondary)
}
.listStyle(.plain)
.scrollContentBackground(.hidden)
.background(Color.appBackgroundPrimary)
.navigationTitle("Profile")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("Cancel") {
dismiss()
}
}
}
.onChange(of: viewModel.firstName) { _, _ in
viewModel.clearMessages()
}
.onChange(of: viewModel.lastName) { _, _ in
viewModel.clearMessages()
}
.onChange(of: viewModel.email) { _, _ in
viewModel.clearMessages()
}
.handleErrors(
error: viewModel.errorMessage,
onRetry: { viewModel.updateProfile() }
)
}
}
}
}
#Preview {
ProfileView()
}