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