Add contractor management and integrate with task completions

Features:
- Add full contractor CRUD functionality (Android & iOS)
- Add contractor selection to task completion dialog
- Display contractor info in completion cards
- Add ContractorSpecialty model and API integration
- Add contractors tab to bottom navigation
- Replace hardcoded specialty lists with API data
- Update lookup endpoints to return arrays instead of paginated responses

Changes:
- Add Contractor models (ContractorSummary, ContractorDetail, ContractorCreate/UpdateRequest)
- Add ContractorApi with endpoints for list, detail, create, update, delete, toggle favorite
- Add ContractorViewModel for state management
- Add ContractorsScreen and ContractorDetailScreen for Android
- Add AddContractorDialog with form validation
- Add Contractor views for iOS (list, detail, form)
- Update CompleteTaskDialog to include contractor selection
- Update CompletionCardView to show contractor name and phone
- Add contractor field to TaskCompletion model
- Update LookupsApi to return List<T> instead of paginated responses
- Update LookupsRepository and LookupsViewModel to handle array responses
- Update LookupsManager (iOS) to handle array responses for contractor specialties

🤖 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-10 19:39:41 -06:00
parent 764a90cb41
commit d3caffa792
25 changed files with 3506 additions and 29 deletions

View File

@@ -31,7 +31,27 @@ struct CompletionCardView: View {
}
}
if let completedBy = completion.completedByName {
// Display contractor or manual entry
if let contractorDetails = completion.contractorDetails {
HStack(alignment: .top, spacing: 6) {
Image(systemName: "wrench.and.screwdriver")
.font(.caption2)
.foregroundColor(AppColors.primary)
VStack(alignment: .leading, spacing: 2) {
Text("By: \(contractorDetails.name)")
.font(.caption2)
.fontWeight(.medium)
.foregroundColor(.primary)
if let company = contractorDetails.company {
Text(company)
.font(.caption2)
.foregroundColor(.secondary)
}
}
}
} else if let completedBy = completion.completedByName {
Text("By: \(completedBy)")
.font(.caption2)
.foregroundColor(.secondary)