Add shared utilities and refactor iOS codebase for DRY compliance

Create centralized shared utilities in iosApp/Shared/:
- Extensions: ViewExtensions, DateExtensions, StringExtensions, DoubleExtensions
- Components: FormComponents, SharedEmptyStateView, ButtonStyles
- Modifiers: CardModifiers
- Utilities: ValidationHelpers, ErrorMessages

Migrate existing views to use shared utilities:
- LoginView: Use IconTextField, FieldLabel, FieldError, OrganicPrimaryButton
- TaskFormView: Use .loadingOverlay() modifier
- TaskCard/DynamicTaskCard: Use .toFormattedDate() extension
- CompletionCardView: Use .toCurrency() (with KotlinDouble support)
- ResidenceDetailView: Use OrganicEmptyState, StandardLoadingView
- Profile views: Use .standardFormStyle(), .sectionBackground()
- Form views: Use consistent form styling modifiers

Benefits:
- Eliminates ~180 lines of duplicate code
- Consistent styling across all forms and components
- KotlinDouble extensions for seamless KMM interop
- Single source of truth for UI patterns

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-17 13:19:59 -06:00
parent 44c7b23cc2
commit 42eda6a8c8
28 changed files with 3607 additions and 287 deletions
+12 -14
View File
@@ -53,7 +53,7 @@ struct CompleteTaskView: View {
} header: {
Text(L10n.Tasks.taskDetails)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Contractor Selection Section
Section {
@@ -91,7 +91,7 @@ struct CompleteTaskView: View {
} footer: {
Text(L10n.Tasks.contractorHelper)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Completion Details Section
Section {
@@ -121,7 +121,7 @@ struct CompleteTaskView: View {
} footer: {
Text(L10n.Tasks.optionalDetails)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Notes Section
Section {
@@ -138,7 +138,7 @@ struct CompleteTaskView: View {
} footer: {
Text(L10n.Tasks.optionalNotes)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Rating Section
Section {
@@ -172,7 +172,7 @@ struct CompleteTaskView: View {
} footer: {
Text(L10n.Tasks.rateQuality)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Images Section
Section {
@@ -236,7 +236,7 @@ struct CompleteTaskView: View {
} footer: {
Text(L10n.Tasks.addPhotos)
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Complete Button Section
Section {
@@ -257,8 +257,7 @@ struct CompleteTaskView: View {
.disabled(isSubmitting)
}
}
.listStyle(.plain)
.scrollContentBackground(.hidden)
.standardFormStyle()
.background(WarmGradientBackground())
.navigationTitle(L10n.Tasks.completeTask)
.navigationBarTitleDisplayMode(.inline)
@@ -401,7 +400,7 @@ struct ContractorPickerView: View {
}
}
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
// Contractors list
if contractorViewModel.isLoading {
@@ -411,12 +410,12 @@ struct ContractorPickerView: View {
.tint(Color.appPrimary)
Spacer()
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
} else if let errorMessage = contractorViewModel.errorMessage {
Text(errorMessage)
.foregroundColor(Color.appError)
.font(.caption)
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
} else {
ForEach(contractorViewModel.contractors, id: \.id) { contractor in
Button(action: {
@@ -453,12 +452,11 @@ struct ContractorPickerView: View {
}
}
}
.listRowBackground(Color.appBackgroundSecondary)
.sectionBackground()
}
}
}
.listStyle(.plain)
.scrollContentBackground(.hidden)
.standardFormStyle()
.background(WarmGradientBackground())
.navigationTitle(L10n.Tasks.selectContractor)
.navigationBarTitleDisplayMode(.inline)