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:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user