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 { var body: some View {
ZStack { ZStack {
Color(.systemGroupedBackground) AppColors.background
.ignoresSafeArea() .ignoresSafeArea()
if viewModel.isLoading { 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 { } else if let error = viewModel.errorMessage {
ErrorView(message: error) { ErrorView(message: error) {
viewModel.loadMyResidences() viewModel.loadMyResidences()
@@ -21,33 +27,37 @@ struct ResidencesListView: View {
if response.residences.isEmpty { if response.residences.isEmpty {
EmptyResidencesView() EmptyResidencesView()
} else { } else {
ScrollView { ScrollView(showsIndicators: false) {
VStack(spacing: 16) { VStack(spacing: AppSpacing.lg) {
// Summary Card // Summary Card
SummaryCard(summary: response.summary) SummaryCard(summary: response.summary)
.padding(.horizontal) .padding(.horizontal, AppSpacing.md)
.padding(.top) .padding(.top, AppSpacing.sm)
// Properties Header // Properties Header
HStack { HStack {
Text("Your Properties") VStack(alignment: .leading, spacing: AppSpacing.xxs) {
.font(.title2) Text("Your Properties")
.fontWeight(.bold) .font(AppTypography.headlineSmall)
.foregroundColor(AppColors.textPrimary)
Text("\(response.residences.count) \(response.residences.count == 1 ? "property" : "properties")")
.font(AppTypography.bodySmall)
.foregroundColor(AppColors.textSecondary)
}
Spacer() Spacer()
} }
.padding(.horizontal) .padding(.horizontal, AppSpacing.md)
.padding(.top, 8)
// Residences List // Residences List
ForEach(response.residences, id: \.id) { residence in ForEach(response.residences, id: \.id) { residence in
NavigationLink(destination: ResidenceDetailView(residenceId: residence.id)) { NavigationLink(destination: ResidenceDetailView(residenceId: residence.id)) {
ResidenceCard(residence: residence) ResidenceCard(residence: residence)
.padding(.horizontal, AppSpacing.md)
} }
.buttonStyle(PlainButtonStyle()) .buttonStyle(PlainButtonStyle())
} }
.padding(.horizontal)
} }
.padding(.bottom) .padding(.bottom, AppSpacing.md)
} }
} }
} }
@@ -60,12 +70,16 @@ struct ResidencesListView: View {
showingJoinResidence = true showingJoinResidence = true
}) { }) {
Image(systemName: "person.badge.plus") Image(systemName: "person.badge.plus")
.font(.system(size: 18, weight: .semibold))
.foregroundColor(AppColors.primary)
} }
Button(action: { Button(action: {
showingAddResidence = true 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 let priority: String
var body: some View { var body: some View {
HStack(spacing: 4) { HStack(spacing: AppSpacing.xxs) {
Image(systemName: "exclamationmark.circle.fill") Image(systemName: "exclamationmark.circle.fill")
.font(.caption2) .font(.system(size: 10, weight: .bold))
Text(priority.capitalized) Text(priority.capitalized)
.font(.caption) .font(AppTypography.labelSmall)
.fontWeight(.medium) .fontWeight(.semibold)
} }
.padding(.horizontal, 8) .padding(.horizontal, AppSpacing.sm)
.padding(.vertical, 4) .padding(.vertical, AppSpacing.xxs)
.background(priorityColor.opacity(0.2)) .background(priorityColor.opacity(0.15))
.foregroundColor(priorityColor) .foregroundColor(priorityColor)
.cornerRadius(6) .cornerRadius(AppRadius.xs)
} }
private var priorityColor: Color { private var priorityColor: Color {
switch priority.lowercased() { switch priority.lowercased() {
case "high": return .red case "high": return AppColors.error
case "medium": return .orange case "medium": return AppColors.warning
case "low": return .green case "low": return AppColors.success
default: return .gray default: return AppColors.textTertiary
} }
} }
} }
@@ -36,4 +36,5 @@ struct PriorityBadge: View {
PriorityBadge(priority: "low") PriorityBadge(priority: "low")
} }
.padding() .padding()
.background(AppColors.background)
} }

View File

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