import SwiftUI struct HistoryScreen: View { @EnvironmentObject var appState: AppState @State private var history: [ScanHistoryItem] = [] @State private var isLoading = true @State private var selectedProduct: Product? var body: some View { NavigationStack { Group { if !appState.isAuthenticated { // Not logged in VStack(spacing: 20) { Spacer() Image(systemName: "clock.fill") .font(.system(size: 60)) .foregroundColor(.gray) Text("Track Your Scans") .font(.title2.bold()) Text("Log in to keep a history of all the products you've scanned.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, 40) Button { appState.showLoginSheet = true } label: { Text("Log In") .font(.headline) .foregroundColor(.black) .frame(maxWidth: .infinity) .padding() .background(Color.green) .cornerRadius(12) } .padding(.horizontal, 40) Spacer() } } else if isLoading { ProgressView("Loading history...") } else if history.isEmpty { VStack(spacing: 20) { Spacer() Image(systemName: "clock") .font(.system(size: 60)) .foregroundColor(.gray) Text("No Scan History") .font(.title2.bold()) Text("Products you scan will appear here.") .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) .padding(.horizontal, 40) Spacer() } } else { List { ForEach(history) { item in HistoryRow(item: item) .onTapGesture { selectedProduct = item.product } } } .listStyle(.plain) } } .navigationTitle("History") .navigationDestination(isPresented: Binding( get: { selectedProduct != nil }, set: { if !$0 { selectedProduct = nil } } )) { if let product = selectedProduct { ProductScreen(product: product) .environmentObject(appState) } } .task { if appState.isAuthenticated { await loadHistory() } } .refreshable { await loadHistory() } } } private func loadHistory() async { isLoading = true do { let result = try await APIService.shared.getHistory() await MainActor.run { history = result isLoading = false } } catch { await MainActor.run { isLoading = false appState.showError(error.localizedDescription) } } } } struct HistoryRow: View { let item: ScanHistoryItem var body: some View { HStack(spacing: 12) { // Product Image if let imageURL = item.product.imageURL { AsyncImage(url: imageURL) { phase in switch phase { case .success(let image): image .resizable() .aspectRatio(contentMode: .fill) case .failure: imagePlaceholder default: ProgressView() } } .frame(width: 50, height: 50) .background(Color(.systemGray6)) .cornerRadius(8) .clipped() } else { imagePlaceholder .frame(width: 50, height: 50) } VStack(alignment: .leading, spacing: 4) { Text(item.product.name) .font(.subheadline.bold()) .lineLimit(1) Text(item.product.brand) .font(.caption) .foregroundColor(.secondary) } Spacer() VStack(alignment: .trailing, spacing: 4) { // Score HStack(spacing: 4) { Circle() .fill(scoreColor(item.product.score)) .frame(width: 8, height: 8) Text("\(item.product.score)") .font(.caption.bold()) } // Time ago Text(item.formattedDate) .font(.caption2) .foregroundColor(.secondary) } } .padding(.vertical, 4) } private var imagePlaceholder: some View { ZStack { Color(.systemGray5) Image(systemName: "carrot.fill") .font(.caption) .foregroundColor(.gray) } .cornerRadius(8) } private func scoreColor(_ score: Int) -> Color { switch score { case 80...100: return .green case 50..<80: return .yellow case 30..<50: return .orange default: return .red } } }