import SwiftUI struct HomeView: View { @Environment(AuthManager.self) private var authManager @State private var viewModel = HomeViewModel() var body: some View { NavigationStack { ScrollView { VStack(spacing: 20) { if viewModel.isLoading { LoadingView(message: "Loading dashboard...") .frame(height: 300) } else { // Quick Stats Card caloriesSummaryCard // Macros Card macrosCard // Quick Actions quickActionsCard } if let error = viewModel.errorMessage { ErrorBanner(message: error) { Task { await viewModel.load() } } } } .padding(16) } .background(Color.canvas) .navigationTitle("Dashboard") .toolbar { ToolbarItem(placement: .topBarTrailing) { Menu { Button(role: .destructive) { authManager.logout() } label: { Label("Sign Out", systemImage: "rectangle.portrait.and.arrow.right") } } label: { Image(systemName: "person.circle.fill") .font(.title3) .foregroundStyle(Color.accentWarm) } } } .refreshable { await viewModel.load() } .task { await viewModel.load() } } } private var caloriesSummaryCard: some View { VStack(spacing: 16) { HStack { VStack(alignment: .leading, spacing: 4) { Text("Today") .font(.headline) .foregroundStyle(Color.text1) Text(Date().displayString) .font(.subheadline) .foregroundStyle(Color.text3) } Spacer() Text("\(viewModel.entryCount) entries") .font(.caption) .foregroundStyle(Color.text4) .padding(.horizontal, 10) .padding(.vertical, 4) .background(Color.surfaceSecondary) .clipShape(Capsule()) } MacroRingLarge( current: viewModel.totalCalories, goal: viewModel.goal.calories, color: .caloriesColor, size: 140, lineWidth: 12 ) HStack(spacing: 0) { macroStat("Eaten", value: Int(viewModel.totalCalories), unit: "kcal") Spacer() macroStat("Remaining", value: Int(max(viewModel.goal.calories - viewModel.totalCalories, 0)), unit: "kcal") Spacer() macroStat("Goal", value: Int(viewModel.goal.calories), unit: "kcal") } } .padding(20) .background(Color.surface) .clipShape(RoundedRectangle(cornerRadius: 16)) .shadow(color: .black.opacity(0.04), radius: 8, y: 4) } private var macrosCard: some View { VStack(spacing: 14) { Text("Macros") .font(.headline) .foregroundStyle(Color.text1) .frame(maxWidth: .infinity, alignment: .leading) HStack(spacing: 20) { MacroRing( current: viewModel.totalProtein, goal: viewModel.goal.protein, color: .proteinColor, label: "Protein", unit: "g", size: 68 ) MacroRing( current: viewModel.totalCarbs, goal: viewModel.goal.carbs, color: .carbsColor, label: "Carbs", unit: "g", size: 68 ) MacroRing( current: viewModel.totalFat, goal: viewModel.goal.fat, color: .fatColor, label: "Fat", unit: "g", size: 68 ) } .frame(maxWidth: .infinity) } .padding(20) .background(Color.surface) .clipShape(RoundedRectangle(cornerRadius: 16)) .shadow(color: .black.opacity(0.04), radius: 8, y: 4) } private var quickActionsCard: some View { VStack(spacing: 12) { Text("Quick Actions") .font(.headline) .foregroundStyle(Color.text1) .frame(maxWidth: .infinity, alignment: .leading) HStack(spacing: 12) { quickActionButton(icon: "plus.circle.fill", label: "Log Food", color: .accentEmerald) quickActionButton(icon: "doc.text.fill", label: "Templates", color: .carbsColor) quickActionButton(icon: "clock.fill", label: "History", color: .accentWarm) } } .padding(20) .background(Color.surface) .clipShape(RoundedRectangle(cornerRadius: 16)) .shadow(color: .black.opacity(0.04), radius: 8, y: 4) } private func macroStat(_ label: String, value: Int, unit: String) -> some View { VStack(spacing: 2) { Text("\(value)") .font(.system(.title3, design: .rounded, weight: .bold)) .foregroundStyle(Color.text1) Text("\(label)") .font(.caption2) .foregroundStyle(Color.text4) } } private func quickActionButton(icon: String, label: String, color: Color) -> some View { VStack(spacing: 8) { Image(systemName: icon) .font(.title2) .foregroundStyle(color) Text(label) .font(.caption) .fontWeight(.medium) .foregroundStyle(Color.text2) } .frame(maxWidth: .infinity) .padding(.vertical, 16) .background(color.opacity(0.06)) .clipShape(RoundedRectangle(cornerRadius: 12)) } }