105 lines
3.5 KiB
Swift
105 lines
3.5 KiB
Swift
import SwiftUI
|
|
import SwiftData
|
|
|
|
/// 趋势 Tab。日历已迁至主页;此页专注「时间序列」:
|
|
/// 任何出现 ≥2 次的指标都能成趋势,分「长期监测」(seriesKey)与「化验指标」(按名归并)两段。
|
|
struct TrendsView: View {
|
|
@Query(sort: \Indicator.capturedAt, order: .reverse)
|
|
private var indicators: [Indicator]
|
|
|
|
@Query private var profiles: [UserProfile]
|
|
@Query private var customMetrics: [CustomMonitorMetric]
|
|
|
|
private var profile: UserProfile? { profiles.first }
|
|
|
|
private var seriesBuckets: [SeriesBucket] {
|
|
SeriesBucket.build(from: indicators,
|
|
profile: profile,
|
|
customMetrics: customMetrics)
|
|
}
|
|
|
|
private var monitorBuckets: [SeriesBucket] {
|
|
seriesBuckets.filter { $0.kind == .monitor }
|
|
}
|
|
private var labBuckets: [SeriesBucket] {
|
|
seriesBuckets.filter { $0.kind == .lab }
|
|
}
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
ScrollView(showsIndicators: false) {
|
|
VStack(alignment: .leading, spacing: 18) {
|
|
header.padding(.top, 4)
|
|
if seriesBuckets.isEmpty {
|
|
emptyState
|
|
} else {
|
|
if !monitorBuckets.isEmpty {
|
|
section(title: String(appLoc: "长期监测"), buckets: monitorBuckets)
|
|
}
|
|
if !labBuckets.isEmpty {
|
|
section(title: String(appLoc: "化验指标趋势"), buckets: labBuckets)
|
|
}
|
|
}
|
|
}
|
|
.padding(.horizontal, 20)
|
|
.padding(.bottom, 24)
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
|
.background(Tj.Palette.sand.ignoresSafeArea())
|
|
.navigationBarHidden(true)
|
|
}
|
|
}
|
|
|
|
private var header: some View {
|
|
Text("趋势")
|
|
.font(.tjTitle(26))
|
|
.foregroundStyle(Tj.Palette.text)
|
|
}
|
|
|
|
private func section(title: String, buckets: [SeriesBucket]) -> some View {
|
|
VStack(alignment: .leading, spacing: 12) {
|
|
HStack(alignment: .lastTextBaseline) {
|
|
Text(title)
|
|
.font(.tjH2())
|
|
.foregroundStyle(Tj.Palette.text)
|
|
Text("\(buckets.count) 项")
|
|
.font(.system(size: 12))
|
|
.foregroundStyle(Tj.Palette.text3)
|
|
Spacer()
|
|
}
|
|
|
|
VStack(spacing: 12) {
|
|
ForEach(buckets) { bucket in
|
|
NavigationLink {
|
|
TrendDetailView(bucket: bucket)
|
|
} label: {
|
|
TrendRow(bucket: bucket)
|
|
}
|
|
.buttonStyle(.plain)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private var emptyState: some View {
|
|
VStack(spacing: 12) {
|
|
TjPlaceholder(label: String(appLoc: "还没有可成趋势的指标"))
|
|
.frame(height: 120)
|
|
.frame(maxWidth: 260)
|
|
Text("同一指标记录满 2 次后,会在这里出现时间序列")
|
|
.font(.system(size: 12))
|
|
.foregroundStyle(Tj.Palette.text3)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.top, 60)
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
TrendsView()
|
|
.modelContainer(for: [
|
|
Indicator.self, Report.self, DiaryEntry.self, Symptom.self, Asset.self
|
|
], inMemory: true)
|
|
}
|