Files
kangkang/康康/Features/Home/TodayRemindersCard.swift
link2026 77a4ee1c37 缺少代码差异信息,无法生成具体的commit message。请提供code differences内容以便分析并生成符合Angular规范的提交信息。
当您提供代码差异后,我将按照以下格式生成:

```
<type>(<scope>): <subject>

<body>
```

其中type会根据更改类型选择(feat、fix、docs、style、refactor等),scope表示影响范围,subject简要描述变更内容,body详细说明修改内容。
2026-06-07 14:17:18 +08:00

119 lines
4.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
import Combine
/// :(CustomReminder)+ (MetricReminder),
/// ;(,)
/// ( EmptyView,)
/// ; (RemindersListView)
struct TodayRemindersCard: View {
@Query(sort: \CustomReminder.updatedAt, order: .reverse)
private var customReminders: [CustomReminder]
@Query(sort: \MetricReminder.updatedAt, order: .reverse)
private var metricReminders: [MetricReminder]
@State private var showingCenter = false
/// ,( OngoingSymptomsCard )
@State private var tick: Date = .now
private let timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
/// , + ,
private var items: [TodayItem] {
let cal = Calendar.current
var arr: [TodayItem] = []
for r in customReminders where r.occurs(on: tick, calendar: cal) {
arr.append(TodayItem(id: "c-\(r.id.uuidString)",
hour: r.hour, minute: r.minute, title: r.title))
}
for r in metricReminders where r.occurs(on: tick, calendar: cal) {
arr.append(TodayItem(id: "m-\(r.metricId)",
hour: r.hour, minute: r.minute, title: r.displayName))
}
return arr.sorted { ($0.hour, $0.minute) < ($1.hour, $1.minute) }
}
var body: some View {
let rows = items
if rows.isEmpty {
EmptyView()
} else {
VStack(alignment: .leading, spacing: 10) {
header(count: rows.count)
VStack(spacing: 8) {
ForEach(rows) { row($0) }
}
}
.padding(.bottom, 18)
.onReceive(timer) { now in tick = now }
.sheet(isPresented: $showingCenter) {
// NavigationStack ;sheet
NavigationStack { RemindersListView(presentedAsSheet: true) }
}
}
}
private func header(count: Int) -> some View {
HStack(spacing: 8) {
Circle()
.fill(Tj.Palette.amber)
.frame(width: 7, height: 7)
Text("今日提醒")
.font(.tjH2())
.foregroundStyle(Tj.Palette.text)
Text("\(count)")
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
Spacer()
Button { showingCenter = true } label: {
Text("全部 ")
.font(.tjScaled( 12))
.foregroundStyle(Tj.Palette.text3)
}
.buttonStyle(.plain)
}
}
private func row(_ item: TodayItem) -> some View {
let isPast = item.isPast(now: tick)
return HStack(spacing: 12) {
Text(item.timeLabel)
.font(.tjScaled( 14, weight: .semibold).monospacedDigit())
.foregroundStyle(isPast ? Tj.Palette.text3 : Tj.Palette.ink)
.frame(width: 46, alignment: .leading)
Image(systemName: "bell.fill")
.font(.tjScaled( 12))
.foregroundStyle(isPast ? Tj.Palette.text3 : Tj.Palette.amber)
Text(item.title)
.font(.tjScaled( 15, weight: .medium))
.foregroundStyle(isPast ? Tj.Palette.text3 : Tj.Palette.text)
.lineLimit(1)
Spacer(minLength: 0)
}
.padding(.horizontal, 14)
.padding(.vertical, 12)
.background(
RoundedRectangle(cornerRadius: Tj.Radius.sm, style: .continuous)
.fill(Tj.Palette.paper)
)
.shadow(color: Color(red: 0.196, green: 0.157, blue: 0.098).opacity(0.04),
radius: 2, x: 0, y: 1)
}
}
/// ()
private struct TodayItem: Identifiable {
let id: String
let hour: Int
let minute: Int
let title: String
var timeLabel: String { String(format: "%02d:%02d", hour, minute) }
/// ()
func isPast(now: Date) -> Bool {
let c = Calendar.current.dateComponents([.hour, .minute], from: now)
let nowMinutes = (c.hour ?? 0) * 60 + (c.minute ?? 0)
return hour * 60 + minute < nowMinutes
}
}