import SwiftUI /// Corpus-health overview (not a dumped table). Stat hero + domain distribution bars; tapping a /// domain jumps to Documents (cross-page nav proof). struct DashboardView: View { @Environment(AppModel.self) private var model var body: some View { ScrollView { VStack(alignment: .leading, spacing: 18) { if let s = model.stats { LazyVGrid(columns: [GridItem(.adaptive(minimum: 150), spacing: 12)], spacing: 12) { StatCard(title: "전체", value: s.total, color: Sage.brand) StatCard(title: "문서", value: s.counts["document"] ?? 0, color: Sage.brand) StatCard(title: "승인 대기", value: s.libraryPendingSuggestions, color: Sage.amber) } VStack(alignment: .leading, spacing: 10) { Text("카테고리 분포").font(.headline).foregroundStyle(Sage.ink) ForEach(s.counts.sorted { $0.value > $1.value }, id: \.key) { key, value in DomainBar(name: Self.categoryLabel(key), count: value, max: s.counts.values.max() ?? 1) .contentShape(Rectangle()) .onTapGesture { model.section = .documents } } } .padding(16) .background(Sage.card, in: RoundedRectangle(cornerRadius: 14)) .overlay(RoundedRectangle(cornerRadius: 14).stroke(Sage.line)) } else { ProgressView().frame(maxWidth: .infinity, minHeight: 200) } } .padding(20) } .background(Sage.surface) } /// 서버 category enum → 표시명 (미등록 키는 raw 노출 — 신규 카테고리 추가에 안전). static func categoryLabel(_ key: String) -> String { switch key { case "document": return "문서" case "library": return "자료실" case "news": return "뉴스" case "law": return "법령" case "memo": return "메모" case "audio": return "오디오" case "video": return "비디오" default: return key } } }