EditProfileModalView.swift 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import SwiftUI
  2. /// Modal Sheet allowing logged-in users to update their profile (nickname, email, phone).
  3. struct EditProfileModalView: View {
  4. @Environment(\.dismiss) private var dismiss
  5. @ObservedObject var authManager: AuthManager = .shared
  6. @State private var usernameInput: String = ""
  7. @State private var emailInput: String = ""
  8. @State private var phoneInput: String = ""
  9. @State private var errorMessage: String?
  10. @State private var successToast: String?
  11. var body: some View {
  12. ZStack {
  13. Color.spaceBlack.ignoresSafeArea()
  14. VStack(spacing: 20) {
  15. // Header
  16. HStack {
  17. Text("编辑个人资料")
  18. .font(.system(size: 18, weight: .bold))
  19. .foregroundStyle(Color.primary)
  20. Spacer()
  21. Button {
  22. dismiss()
  23. } label: {
  24. Image(systemName: "xmark.circle.fill")
  25. .font(.system(size: 22))
  26. .foregroundStyle(Color.secondary.opacity(0.6))
  27. }
  28. }
  29. .padding(.horizontal, 20)
  30. .padding(.top, 20)
  31. VStack(spacing: 14) {
  32. inputSection(label: "用户昵称", icon: "person", text: $usernameInput, placeholder: "请输入新的用户昵称")
  33. inputSection(label: "电子邮箱", icon: "envelope", text: $emailInput, placeholder: "绑定/修改电子邮箱")
  34. inputSection(label: "手机号码", icon: "phone", text: $phoneInput, placeholder: "绑定/修改手机号码")
  35. if let error = errorMessage {
  36. Text(error)
  37. .font(.system(size: 12))
  38. .foregroundStyle(Color.recordingRed)
  39. .frame(maxWidth: .infinity, alignment: .leading)
  40. }
  41. if let toast = successToast {
  42. Text(toast)
  43. .font(.system(size: 12))
  44. .foregroundStyle(Color.green)
  45. .frame(maxWidth: .infinity, alignment: .leading)
  46. }
  47. }
  48. .padding(.horizontal, 20)
  49. .padding(.top, 10)
  50. Spacer()
  51. Button {
  52. handleSave()
  53. } label: {
  54. if authManager.isProcessing {
  55. ProgressView()
  56. .tint(Color.spaceBlack)
  57. } else {
  58. Text("保存修改")
  59. .font(.system(size: 15, weight: .semibold))
  60. .foregroundStyle(Color.spaceBlack)
  61. }
  62. }
  63. .frame(maxWidth: .infinity)
  64. .padding(.vertical, 14)
  65. .background(Color.primary)
  66. .cornerRadius(8)
  67. .padding(.horizontal, 20)
  68. .padding(.bottom, 24)
  69. .disabled(authManager.isProcessing)
  70. }
  71. }
  72. .onAppear {
  73. if let user = authManager.currentUser {
  74. usernameInput = user.username
  75. emailInput = user.email ?? ""
  76. phoneInput = user.phoneNumber ?? ""
  77. }
  78. }
  79. }
  80. private func inputSection(label: String, icon: String, text: Binding<String>, placeholder: String) -> some View {
  81. VStack(alignment: .leading, spacing: 6) {
  82. Text(label)
  83. .font(.system(size: 12))
  84. .foregroundStyle(Color.secondary)
  85. HStack(spacing: 12) {
  86. Image(systemName: icon)
  87. .font(.system(size: 14))
  88. .foregroundStyle(Color.secondary)
  89. .frame(width: 20)
  90. TextField(placeholder, text: text)
  91. .font(.system(size: 14))
  92. .autocapitalization(.none)
  93. .disableAutocorrection(true)
  94. }
  95. .padding(.horizontal, 14)
  96. .padding(.vertical, 12)
  97. .background(Color.cardBackground.opacity(0.3))
  98. .businessBorder(cornerRadius: 8)
  99. }
  100. }
  101. private func handleSave() {
  102. errorMessage = nil
  103. successToast = nil
  104. authManager.updateProfile(
  105. username: usernameInput,
  106. email: emailInput,
  107. phoneNumber: phoneInput,
  108. avatarURL: nil
  109. ) { success, err in
  110. if success {
  111. successToast = "个人资料更新成功!"
  112. DispatchQueue.main.asyncAfter(deadline: .now() + 0.8) {
  113. dismiss()
  114. }
  115. } else {
  116. errorMessage = err ?? "保存修改失败"
  117. }
  118. }
  119. }
  120. }