Add comprehensive error handling utilities for all screens

Created reusable error handling components that can be used across all
screens in both Android and iOS apps to show retry/cancel dialogs when
network calls fail.

Android Components:
- ApiResultHandler: Composable that automatically handles ApiResult states
  with loading indicators and error dialogs
- HandleErrors(): Extension function for ApiResult to show error dialogs
  for operations that don't return display data
- Updated ResidencesScreen to import ApiResultHandler

iOS Components:
- ViewStateHandler: SwiftUI view that handles loading/error/success states
  with automatic error alerts
- handleErrors(): View modifier for automatic error monitoring
- Both use the existing ErrorAlertModifier for consistent alerts

Documentation:
- Created ERROR_HANDLING.md with comprehensive usage guide
- Includes examples for data loading and create/update/delete operations
- Migration guide for updating existing screens
- Best practices and testing guidelines

These utilities make it easy to add consistent error handling with retry
functionality to any screen that makes network calls, improving the user
experience across the entire app.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-14 14:28:09 -06:00
parent 0e3b9681f6
commit 1d3a06f492
4 changed files with 285 additions and 98 deletions

View File

@@ -0,0 +1,112 @@
import SwiftUI
/// A view that handles loading, error, and success states with automatic error alerts
///
/// Example usage:
/// ```swift
/// ViewStateHandler(
/// isLoading: viewModel.isLoading,
/// error: viewModel.errorMessage,
/// onRetry: { viewModel.loadData() }
/// ) {
/// // Success content
/// List(items) { item in
/// Text(item.name)
/// }
/// }
/// ```
struct ViewStateHandler<Content: View>: View {
let isLoading: Bool
let error: String?
let onRetry: () -> Void
let content: Content
@State private var errorAlert: ErrorAlertInfo? = nil
init(
isLoading: Bool,
error: String?,
onRetry: @escaping () -> Void,
@ViewBuilder content: () -> Content
) {
self.isLoading = isLoading
self.error = error
self.onRetry = onRetry
self.content = content()
}
var body: some View {
ZStack {
if isLoading {
ProgressView()
.scaleEffect(1.5)
} else {
content
}
}
.onChange(of: error) { errorMessage in
if let errorMessage = errorMessage, !errorMessage.isEmpty {
errorAlert = ErrorAlertInfo(message: errorMessage)
}
}
.errorAlert(
error: errorAlert,
onRetry: {
errorAlert = nil
onRetry()
},
onDismiss: {
errorAlert = nil
}
)
}
}
/// Extension to add automatic error handling to any view
extension View {
/// Monitors an error message and shows error alert when it changes
///
/// Example usage:
/// ```swift
/// Form {
/// // Form fields
/// }
/// .handleErrors(
/// error: viewModel.errorMessage,
/// onRetry: { viewModel.submitForm() }
/// )
/// ```
func handleErrors(
error: String?,
onRetry: @escaping () -> Void
) -> some View {
modifier(ErrorHandlerModifier(error: error, onRetry: onRetry))
}
}
/// View modifier that handles errors automatically
private struct ErrorHandlerModifier: ViewModifier {
let error: String?
let onRetry: () -> Void
@State private var errorAlert: ErrorAlertInfo? = nil
func body(content: Content) -> some View {
content
.onChange(of: error) { errorMessage in
if let errorMessage = errorMessage, !errorMessage.isEmpty {
errorAlert = ErrorAlertInfo(message: errorMessage)
}
}
.errorAlert(
error: errorAlert,
onRetry: {
errorAlert = nil
onRetry()
},
onDismiss: {
errorAlert = nil
}
)
}
}