Modernize remaining views and badge components

Completed modernization of list views and badge components to match the new design system.

ResidencesListView:
- Modern background color from design system
- Improved loading state with text
- Property count display under header
- Modern toolbar icons with primary color
- Consistent spacing and padding

StatusBadge & PriorityBadge:
- Updated to use AppColors for semantic states
- Applied AppTypography for consistent font sizing
- Used AppSpacing for uniform padding
- Applied AppRadius for consistent corner radius
- Color-coded states (success, warning, error)
- Improved icon sizing and weight

All components now fully integrated with the design system:
- AppColors for all colors
- AppTypography for all text
- AppSpacing for all spacing
- AppRadius for all corner radii
- AppShadow for depth and elevation

The iOS app now has a completely modern, cohesive UI across all views.

🤖 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 11:56:15 -06:00
parent 9305371276
commit e13448083c
3 changed files with 54 additions and 36 deletions

View File

@@ -8,11 +8,17 @@ struct ResidencesListView: View {
var body: some View {
ZStack {
Color(.systemGroupedBackground)
AppColors.background
.ignoresSafeArea()
if viewModel.isLoading {
ProgressView()
VStack(spacing: AppSpacing.lg) {
ProgressView()
.scaleEffect(1.2)
Text("Loading properties...")
.font(AppTypography.bodyMedium)
.foregroundColor(AppColors.textSecondary)
}
} else if let error = viewModel.errorMessage {
ErrorView(message: error) {
viewModel.loadMyResidences()
@@ -21,33 +27,37 @@ struct ResidencesListView: View {
if response.residences.isEmpty {
EmptyResidencesView()
} else {
ScrollView {
VStack(spacing: 16) {
ScrollView(showsIndicators: false) {
VStack(spacing: AppSpacing.lg) {
// Summary Card
SummaryCard(summary: response.summary)
.padding(.horizontal)
.padding(.top)
.padding(.horizontal, AppSpacing.md)
.padding(.top, AppSpacing.sm)
// Properties Header
HStack {
Text("Your Properties")
.font(.title2)
.fontWeight(.bold)
VStack(alignment: .leading, spacing: AppSpacing.xxs) {
Text("Your Properties")
.font(AppTypography.headlineSmall)
.foregroundColor(AppColors.textPrimary)
Text("\(response.residences.count) \(response.residences.count == 1 ? "property" : "properties")")
.font(AppTypography.bodySmall)
.foregroundColor(AppColors.textSecondary)
}
Spacer()
}
.padding(.horizontal)
.padding(.top, 8)
.padding(.horizontal, AppSpacing.md)
// Residences List
ForEach(response.residences, id: \.id) { residence in
NavigationLink(destination: ResidenceDetailView(residenceId: residence.id)) {
ResidenceCard(residence: residence)
.padding(.horizontal, AppSpacing.md)
}
.buttonStyle(PlainButtonStyle())
}
.padding(.horizontal)
}
.padding(.bottom)
.padding(.bottom, AppSpacing.md)
}
}
}
@@ -60,12 +70,16 @@ struct ResidencesListView: View {
showingJoinResidence = true
}) {
Image(systemName: "person.badge.plus")
.font(.system(size: 18, weight: .semibold))
.foregroundColor(AppColors.primary)
}
Button(action: {
showingAddResidence = true
}) {
Image(systemName: "plus")
Image(systemName: "plus.circle.fill")
.font(.system(size: 22, weight: .semibold))
.foregroundColor(AppColors.primary)
}
}
}

View File

@@ -4,27 +4,27 @@ struct PriorityBadge: View {
let priority: String
var body: some View {
HStack(spacing: 4) {
HStack(spacing: AppSpacing.xxs) {
Image(systemName: "exclamationmark.circle.fill")
.font(.caption2)
.font(.system(size: 10, weight: .bold))
Text(priority.capitalized)
.font(.caption)
.fontWeight(.medium)
.font(AppTypography.labelSmall)
.fontWeight(.semibold)
}
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(priorityColor.opacity(0.2))
.padding(.horizontal, AppSpacing.sm)
.padding(.vertical, AppSpacing.xxs)
.background(priorityColor.opacity(0.15))
.foregroundColor(priorityColor)
.cornerRadius(6)
.cornerRadius(AppRadius.xs)
}
private var priorityColor: Color {
switch priority.lowercased() {
case "high": return .red
case "medium": return .orange
case "low": return .green
default: return .gray
case "high": return AppColors.error
case "medium": return AppColors.warning
case "low": return AppColors.success
default: return AppColors.textTertiary
}
}
}
@@ -36,4 +36,5 @@ struct PriorityBadge: View {
PriorityBadge(priority: "low")
}
.padding()
.background(AppColors.background)
}

View File

@@ -5,28 +5,30 @@ struct StatusBadge: View {
var body: some View {
Text(formatStatus(status))
.font(.caption)
.padding(.horizontal, 8)
.padding(.vertical, 4)
.background(statusColor.opacity(0.2))
.font(AppTypography.labelSmall)
.fontWeight(.semibold)
.padding(.horizontal, AppSpacing.sm)
.padding(.vertical, AppSpacing.xxs)
.background(statusColor.opacity(0.15))
.foregroundColor(statusColor)
.cornerRadius(6)
.cornerRadius(AppRadius.xs)
}
private func formatStatus(_ status: String) -> String {
switch status {
case "in_progress": return "In Progress"
case "cancelled": return "Cancelled"
default: return status.capitalized
}
}
private var statusColor: Color {
switch status {
case "completed": return .green
case "in_progress": return .blue
case "pending": return .orange
case "cancelled": return .red
default: return .gray
case "completed": return AppColors.success
case "in_progress": return AppColors.taskInProgress
case "pending": return AppColors.warning
case "cancelled": return AppColors.error
default: return AppColors.textTertiary
}
}
}
@@ -39,4 +41,5 @@ struct StatusBadge: View {
StatusBadge(status: "cancelled")
}
.padding()
.background(AppColors.background)
}