// // CandidatesView.swift // iris // // Created by Codex. // import SwiftUI struct CandidatesView: View { @StateObject private var model = CandidatesViewModel() var body: some View { NavigationStack { List { Section("Source") { LabeledContent("Location") { Text("London (demo)") } if let updated = model.lastUpdatedAt { LabeledContent("Last update") { Text(timeOnly(from: updated)) } } else { LabeledContent("Last update") { Text("Never") } } if let error = model.lastError { Text(error) .font(.footnote) .foregroundStyle(.secondary) } } if !model.diagnostics.isEmpty { Section("Diagnostics") { ForEach(model.diagnostics.keys.sorted(), id: \.self) { key in LabeledContent(key) { Text(model.diagnostics[key] ?? "") .font(.caption) .foregroundStyle(.secondary) .textSelection(.enabled) } } } } Section("Candidates (\(model.candidates.count))") { if model.candidates.isEmpty { Text(model.isLoading ? "Loading…" : "No candidates") .foregroundStyle(.secondary) } else { ForEach(model.candidates, id: \.id) { candidate in CandidateRow(candidate: candidate) } } } } .navigationTitle("Candidates") .toolbar { ToolbarItem(placement: .topBarTrailing) { Button(model.isLoading ? "Refreshing…" : "Refresh") { model.refresh() } .disabled(model.isLoading) } } .onAppear { model.refresh() } } } private func timeOnly(from date: Date) -> String { let formatter = DateFormatter() formatter.dateStyle = .none formatter.timeStyle = .medium return formatter.string(from: date) } } private struct CandidateRow: View { let candidate: FeedItem var body: some View { VStack(alignment: .leading, spacing: 6) { HStack(alignment: .firstTextBaseline) { Text(candidate.title) .font(.headline) .lineLimit(1) Spacer() Text(candidate.type.rawValue) .font(.caption) .foregroundStyle(.secondary) } if !candidate.subtitle.isEmpty { Text(candidate.subtitle) .font(.subheadline) .foregroundStyle(.secondary) .lineLimit(1) } HStack(spacing: 12) { Text(String(format: "prio %.2f", candidate.priority)) Text("ttl \(candidate.ttlSec)s") } .font(.caption) .foregroundStyle(.secondary) } .padding(.vertical, 4) } } struct CandidatesView_Previews: PreviewProvider { static var previews: some View { CandidatesView() } }