Files
honeyDueKMP/iosApp/iosApp/Subviews/Task/CompletionCardView.swift
Trey t a2de0f3454 Migrate iOS app to system colors and improve UI/UX
- Remove AppColors struct, migrate to iOS system colors throughout
- Redesign ContractorFormSheet to use native SwiftUI Form components
- Add color-coded icons to contractor form sections
- Improve dark mode contrast for task cards
- Add background colors to document detail fields
- Fix text alignment issues in ContractorDetailView
- Make task completion lists expandable/collapsible by default
- Clear app badge on launch and when app becomes active
- Update button styling with proper gradients and shadows
- Improve form field focus states and accessibility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 22:22:52 -06:00

121 lines
4.2 KiB
Swift

import SwiftUI
import ComposeApp
struct CompletionCardView: View {
let completion: TaskCompletion
@State private var showPhotoSheet = false
var body: some View {
VStack(alignment: .leading, spacing: 8) {
HStack {
Text(formatDate(completion.completionDate))
.font(.caption)
.fontWeight(.semibold)
.foregroundColor(.blue)
Spacer()
if let rating = completion.rating {
HStack(spacing: 2) {
Image(systemName: "star.fill")
.font(.caption2)
Text("\(rating)")
.font(.caption)
.fontWeight(.bold)
}
.foregroundColor(.orange)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(Color.orange.opacity(0.1))
.cornerRadius(6)
}
}
// Display contractor or manual entry
if let contractorDetails = completion.contractorDetails {
HStack(alignment: .top, spacing: 6) {
Image(systemName: "wrench.and.screwdriver")
.font(.caption2)
.foregroundColor(.blue)
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)
}
if let cost = completion.actualCost {
Text("Cost: $\(cost)")
.font(.caption2)
.foregroundColor(.green)
.fontWeight(.medium)
}
if let notes = completion.notes {
Text(notes)
.font(.caption2)
.foregroundColor(.secondary)
.lineLimit(2)
}
// Show button to view photos if images exist
if let images = completion.images, !images.isEmpty {
Button(action: {
showPhotoSheet = true
}) {
HStack {
Image(systemName: "photo.on.rectangle")
.font(.caption)
Text("View Photos (\(images.count))")
.font(.caption)
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 8)
.background(Color.blue.opacity(0.1))
.foregroundColor(.blue)
.cornerRadius(8)
}
}
}
.padding(12)
.background(Color(.systemGray6))
.cornerRadius(8)
.sheet(isPresented: $showPhotoSheet) {
if let images = completion.images {
PhotoViewerSheet(images: images)
}
}
}
private func formatDate(_ dateString: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
if let date = formatter.date(from: dateString) {
formatter.dateStyle = .medium
formatter.timeStyle = .none
return formatter.string(from: date)
}
// Try without time
formatter.dateFormat = "yyyy-MM-dd"
if let date = formatter.date(from: dateString) {
formatter.dateStyle = .medium
return formatter.string(from: date)
}
return dateString
}
}