68 lines
2.5 KiB
Swift
68 lines
2.5 KiB
Swift
// ── Firing Card ────────────────────────────────────────────────
|
|
// Inline card for non-critical firing timers
|
|
|
|
import SwiftUI
|
|
|
|
struct FiringCard: View {
|
|
let timer: CMTimer
|
|
|
|
@EnvironmentObject var store: TimerStore
|
|
@State private var pulse = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: CMSpacing.md) {
|
|
HStack {
|
|
UrgencyBadge(urgency: timer.urgency)
|
|
|
|
Spacer()
|
|
|
|
Text("NOW")
|
|
.font(CMFonts.body(size: 12, weight: .bold))
|
|
.foregroundStyle(CMColors.urgencyColor(timer.urgency))
|
|
.opacity(pulse ? 1.0 : 0.5)
|
|
.animation(.easeInOut(duration: 0.8).repeatForever(autoreverses: true), value: pulse)
|
|
}
|
|
|
|
Text(timer.label)
|
|
.font(CMFonts.body(size: 20, weight: .bold))
|
|
.foregroundStyle(CMColors.text)
|
|
|
|
HStack(spacing: CMSpacing.md) {
|
|
Button {
|
|
HapticEngine.tap()
|
|
store.snooze(timer.id, minutes: 5)
|
|
} label: {
|
|
Label("Snooze 5m", systemImage: "moon.zzz")
|
|
.font(CMFonts.body(size: 14, weight: .medium))
|
|
.foregroundStyle(CMColors.text)
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, CMSpacing.md)
|
|
.background(CMColors.surfaceHover)
|
|
.clipShape(RoundedRectangle(cornerRadius: CMRadius.sm))
|
|
}
|
|
|
|
Button {
|
|
HapticEngine.tap()
|
|
store.dismiss(timer.id)
|
|
} label: {
|
|
Text("Dismiss")
|
|
.font(CMFonts.body(size: 14, weight: .semibold))
|
|
.foregroundStyle(.white)
|
|
.frame(maxWidth: .infinity)
|
|
.padding(.vertical, CMSpacing.md)
|
|
.background(CMColors.urgencyColor(timer.urgency))
|
|
.clipShape(RoundedRectangle(cornerRadius: CMRadius.sm))
|
|
}
|
|
}
|
|
}
|
|
.padding(CMSpacing.lg)
|
|
.background(CMColors.urgencyBg(timer.urgency))
|
|
.overlay(
|
|
RoundedRectangle(cornerRadius: CMRadius.lg)
|
|
.stroke(CMColors.urgencyBorder(timer.urgency), lineWidth: 2)
|
|
)
|
|
.clipShape(RoundedRectangle(cornerRadius: CMRadius.lg))
|
|
.onAppear { pulse = true }
|
|
}
|
|
}
|