Add comprehensive error message parsing to prevent raw JSON display
- Created ErrorMessageParser utility for both iOS (Swift) and Android (Kotlin) - Parser detects JSON-formatted error messages and extracts user-friendly text - Identifies when data objects (not errors) are returned and provides generic messages - Updated all API error handling to pass raw error bodies instead of concatenating - Applied ErrorMessageParser across all ViewModels and screens on both platforms - Fixed ContractorApi and DocumentApi to not concatenate error bodies with messages - Updated ApiResultHandler to automatically parse all error messages - Error messages now show "Request failed. Please check your input and try again." instead of raw JSON 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -89,7 +89,7 @@ struct JoinResidenceView: View {
|
||||
break
|
||||
} else if let error = state as? ApiResultError {
|
||||
await MainActor.run {
|
||||
viewModel.errorMessage = error.message
|
||||
viewModel.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
viewModel.sharedViewModel.resetJoinResidenceState()
|
||||
}
|
||||
break
|
||||
|
||||
@@ -100,7 +100,7 @@ struct ManageUsersView: View {
|
||||
self.ownerId = responseData.ownerId as? Int32
|
||||
self.isLoading = false
|
||||
} else if let errorResult = result as? ApiResultError {
|
||||
self.errorMessage = errorResult.message
|
||||
self.errorMessage = ErrorMessageParser.parse(errorResult.message)
|
||||
self.isLoading = false
|
||||
} else {
|
||||
self.errorMessage = "Failed to load users"
|
||||
@@ -149,7 +149,7 @@ struct ManageUsersView: View {
|
||||
self.shareCode = successResult.data
|
||||
self.isGeneratingCode = false
|
||||
} else if let errorResult = result as? ApiResultError {
|
||||
self.errorMessage = errorResult.message
|
||||
self.errorMessage = ErrorMessageParser.parse(errorResult.message)
|
||||
self.isGeneratingCode = false
|
||||
} else {
|
||||
self.errorMessage = "Failed to generate share code"
|
||||
@@ -177,7 +177,7 @@ struct ManageUsersView: View {
|
||||
// Remove user from local list
|
||||
self.users.removeAll { $0.id == userId }
|
||||
} else if let errorResult = result as? ApiResultError {
|
||||
self.errorMessage = errorResult.message
|
||||
self.errorMessage = ErrorMessageParser.parse(errorResult.message)
|
||||
} else {
|
||||
self.errorMessage = "Failed to remove user"
|
||||
}
|
||||
|
||||
@@ -148,6 +148,10 @@ struct ResidenceDetailView: View {
|
||||
.onAppear {
|
||||
loadResidenceData()
|
||||
}
|
||||
.handleErrors(
|
||||
error: viewModel.errorMessage,
|
||||
onRetry: { loadResidenceData() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +162,6 @@ private extension ResidenceDetailView {
|
||||
var mainContent: some View {
|
||||
if !hasAppeared || viewModel.isLoading {
|
||||
loadingView
|
||||
} else if let error = viewModel.errorMessage {
|
||||
ErrorView(message: error) {
|
||||
loadResidenceData()
|
||||
}
|
||||
} else if let residence = viewModel.selectedResidence {
|
||||
contentView(for: residence)
|
||||
}
|
||||
@@ -328,7 +328,7 @@ private extension ResidenceDetailView {
|
||||
if result is ApiResultSuccess<KotlinUnit> {
|
||||
dismiss()
|
||||
} else if let errorResult = result as? ApiResultError {
|
||||
self.viewModel.errorMessage = errorResult.message
|
||||
self.viewModel.errorMessage = ErrorMessageParser.parse(errorResult.message)
|
||||
} else {
|
||||
self.viewModel.errorMessage = "Failed to delete residence"
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
break
|
||||
} else if let error = state as? ApiResultError {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.message
|
||||
self.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
self.isLoading = false
|
||||
}
|
||||
break
|
||||
@@ -74,7 +74,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
break
|
||||
} else if let error = state as? ApiResultError {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.message
|
||||
self.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
self.isLoading = false
|
||||
}
|
||||
break
|
||||
@@ -93,7 +93,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
self.selectedResidence = success.data
|
||||
self.isLoading = false
|
||||
} else if let error = result as? ApiResultError {
|
||||
self.errorMessage = error.message
|
||||
self.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
break
|
||||
} else if let error = state as? ApiResultError {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.message
|
||||
self.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
self.isLoading = false
|
||||
}
|
||||
sharedViewModel.resetCreateState()
|
||||
@@ -156,7 +156,7 @@ class ResidenceViewModel: ObservableObject {
|
||||
break
|
||||
} else if let error = state as? ApiResultError {
|
||||
await MainActor.run {
|
||||
self.errorMessage = error.message
|
||||
self.errorMessage = ErrorMessageParser.parse(error.message)
|
||||
self.isLoading = false
|
||||
}
|
||||
sharedViewModel.resetUpdateState()
|
||||
|
||||
@@ -19,10 +19,6 @@ struct ResidencesListView: View {
|
||||
.font(.body)
|
||||
.foregroundColor(Color(.secondaryLabel))
|
||||
}
|
||||
} else if let error = viewModel.errorMessage {
|
||||
ErrorView(message: error) {
|
||||
viewModel.loadMyResidences()
|
||||
}
|
||||
} else if let response = viewModel.myResidences {
|
||||
if response.residences.isEmpty {
|
||||
EmptyResidencesView()
|
||||
@@ -100,6 +96,10 @@ struct ResidencesListView: View {
|
||||
.onAppear {
|
||||
viewModel.loadMyResidences()
|
||||
}
|
||||
.handleErrors(
|
||||
error: viewModel.errorMessage,
|
||||
onRetry: { viewModel.loadMyResidences() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user