Files
kangkang/康康/Features/Home/HomeView.swift
link2026 60b6ad6d65 缺少代码差异信息,无法生成具体的commit message。
请提供 "code differences" 的具体内容,以便我能够根据代码变更情况生成符合 Angular 规范的中文 commit message。
2026-06-07 09:40:59 +08:00

192 lines
6.7 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import SwiftUI
import SwiftData
struct HomeView: View {
var onTapArchive: () -> Void = {}
@Query(sort: \Indicator.capturedAt, order: .reverse)
private var indicators: [Indicator]
@Query(sort: \Report.reportDate, order: .reverse)
private var reports: [Report]
@Query(sort: \DiaryEntry.createdAt, order: .reverse)
private var diaries: [DiaryEntry]
@Query(sort: \Symptom.startedAt, order: .reverse)
private var symptoms: [Symptom]
/// sheet( C1 )
@State private var selectedEntry: TimelineEntry?
@MainActor
private var recentEntries: [TimelineEntry] {
let all =
TimelineEntry.from(indicators: indicators) +
reports.map(TimelineEntry.from(report:)) +
diaries.map(TimelineEntry.from(diary:)) +
symptoms.map(TimelineEntry.from(symptom:))
return all.sorted { $0.date > $1.date }.prefix(6).map { $0 }
}
private var recentGrouped: [(section: DateSection, items: [TimelineEntry])] {
TimelineGrouping.group(recentEntries)
}
var body: some View {
ScrollView(showsIndicators: false) {
VStack(alignment: .leading, spacing: 0) {
greeting
.padding(.top, 4)
.padding(.bottom, 18)
HomeCalendarCard()
TodayRemindersCard()
OngoingSymptomsCard()
.padding(.bottom, 18)
recentSection
.padding(.bottom, 22)
archiveSection
}
.padding(.horizontal, 20)
.padding(.bottom, 20)
}
.background(Tj.Palette.sand.ignoresSafeArea())
.sheet(item: $selectedEntry) { entry in
if let d = TimelineDetail.resolve(
for: entry,
indicators: indicators, reports: reports,
diaries: diaries, symptoms: symptoms
) {
TimelineEntryDetailView(detail: d)
}
}
}
private var greeting: some View {
HStack(alignment: .top) {
VStack(alignment: .leading, spacing: 4) {
Text(todayLine)
.font(.system(size: 12))
.tracking(1)
.foregroundStyle(Tj.Palette.text3)
Text(greetingWord)
.font(.tjTitle())
.foregroundStyle(Tj.Palette.text)
}
Spacer()
TjLockChip()
.padding(.top, 4)
}
}
private var todayLine: String {
let now = Date()
let day = now.formatted(.dateTime.month().day())
let weekday = now.formatted(.dateTime.weekday(.abbreviated))
return "\(day) · \(weekday)"
}
private var greetingWord: String {
switch Calendar.current.component(.hour, from: Date()) {
case 5..<12: return String(appLoc: "早安")
case 12..<18: return String(appLoc: "下午好")
default: return String(appLoc: "晚上好")
}
}
private var recentSection: some View {
VStack(alignment: .leading, spacing: 10) {
HStack(alignment: .lastTextBaseline) {
Text("最近记录").font(.tjH2()).foregroundStyle(Tj.Palette.text)
Spacer()
Button(action: onTapArchive) {
Text("全部 ")
.font(.system(size: 12))
.foregroundStyle(Tj.Palette.text3)
}
.buttonStyle(.plain)
}
if recentEntries.isEmpty {
emptyRecent
} else {
VStack(alignment: .leading, spacing: 14) {
ForEach(recentGrouped, id: \.section) { group in
VStack(alignment: .leading, spacing: 8) {
Text(group.section.label)
.font(.system(size: 11, weight: .semibold))
.tracking(0.5)
.foregroundStyle(Tj.Palette.text3)
VStack(spacing: 10) {
ForEach(group.items) { entry in
Button {
if TimelineDetail.resolve(
for: entry,
indicators: indicators, reports: reports,
diaries: diaries, symptoms: symptoms
) != nil {
selectedEntry = entry
}
} label: {
TimelineRow(entry: entry)
}
.buttonStyle(.plain)
}
}
}
}
}
}
}
}
private var emptyRecent: some View {
HStack {
Text("还没有任何记录,点底部 + 号开始第一条")
.font(.system(size: 13))
.foregroundStyle(Tj.Palette.text3)
Spacer()
}
.padding(.vertical, 14)
.padding(.horizontal, 16)
.tjCard(bordered: true)
}
private var archiveSection: some View {
VStack(alignment: .leading, spacing: 10) {
Text("影像档案").font(.tjH2()).foregroundStyle(Tj.Palette.text)
Button(action: onTapArchive) {
HStack(spacing: 14) {
TjPlaceholder(label: String(appLoc: "档案 · \(reports.count)"))
.frame(width: 56, height: 56)
VStack(alignment: .leading, spacing: 2) {
Text("我的报告档案")
.font(.system(size: 14, weight: .semibold))
.foregroundStyle(Tj.Palette.text)
Text("\(reports.count) 份 · \(indicators.count) 项指标 · 端侧加密")
.font(.system(size: 11))
.foregroundStyle(Tj.Palette.text3)
}
Spacer()
Image(systemName: "chevron.right")
.font(.system(size: 14, weight: .medium))
.foregroundStyle(Tj.Palette.text3)
}
.padding(14)
.tjCard(bordered: true)
}
.buttonStyle(.plain)
}
}
}
#Preview {
HomeView()
}