107 lines
4.6 KiB
Swift
107 lines
4.6 KiB
Swift
import SwiftUI
|
|
import Bedrock
|
|
|
|
/// Shown when there are active rituals but none scheduled for the current time of day.
|
|
struct TodayNoRitualsForTimeView: View {
|
|
@Bindable var store: RitualStore
|
|
|
|
private var currentTimePeriod: TimeOfDay {
|
|
TimeOfDay.current()
|
|
}
|
|
|
|
private var nextRituals: [Ritual] {
|
|
// Find rituals scheduled for later time periods TODAY
|
|
store.currentRituals.filter { ritual in
|
|
guard let arc = ritual.currentArc, arc.contains(date: Date()) else { return false }
|
|
return ritual.timeOfDay != .anytime && ritual.timeOfDay > currentTimePeriod
|
|
}
|
|
}
|
|
|
|
private var nextRitualTomorrow: Ritual? {
|
|
RitualAnalytics.nextUpcomingRitual(from: store.currentRituals)
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: Design.Spacing.large) {
|
|
SectionHeaderView(
|
|
title: String(localized: "All caught up"),
|
|
subtitle: currentTimePeriod.displayName
|
|
)
|
|
|
|
VStack(spacing: Design.Spacing.large) {
|
|
// Icon
|
|
SymbolIcon(currentTimePeriod.symbolName, size: .hero, color: AppAccent.primary.opacity(0.6))
|
|
.padding(.top, Design.Spacing.large)
|
|
|
|
VStack(spacing: Design.Spacing.xSmall) {
|
|
Text(String(localized: "No rituals scheduled for \(currentTimePeriod.displayName.lowercased())."))
|
|
.typography(.subheading)
|
|
.foregroundStyle(AppTextColors.secondary)
|
|
.multilineTextAlignment(.center)
|
|
|
|
Text(currentTimePeriod.timeRange)
|
|
.typography(.caption)
|
|
.foregroundStyle(AppTextColors.tertiary)
|
|
}
|
|
|
|
// Show upcoming rituals if any
|
|
if !nextRituals.isEmpty {
|
|
VStack(alignment: .leading, spacing: Design.Spacing.medium) {
|
|
Text(String(localized: "Coming up later:"))
|
|
.typography(.caption)
|
|
.foregroundStyle(AppTextColors.tertiary)
|
|
|
|
ForEach(nextRituals) { ritual in
|
|
HStack(spacing: Design.Spacing.small) {
|
|
SymbolIcon(ritual.timeOfDay.symbolName, size: .chevron, color: AppTextColors.secondary)
|
|
|
|
Text(ritual.title)
|
|
.typography(.subheading)
|
|
.foregroundStyle(AppTextColors.primary)
|
|
|
|
Spacer()
|
|
|
|
Text(ritual.timeOfDay.displayName)
|
|
.typography(.caption)
|
|
.foregroundStyle(AppTextColors.tertiary)
|
|
}
|
|
.padding(Design.Spacing.small)
|
|
.background(AppSurface.secondary)
|
|
.clipShape(.rect(cornerRadius: Design.CornerRadius.small))
|
|
}
|
|
}
|
|
.padding(.top, Design.Spacing.small)
|
|
} else if let tomorrowRitual = nextRitualTomorrow {
|
|
let format = String(localized: "Next ritual: Tomorrow %@ (%@)")
|
|
Text(String.localizedStringWithFormat(
|
|
format,
|
|
tomorrowRitual.timeOfDay.displayName,
|
|
tomorrowRitual.timeOfDay.timeRange
|
|
))
|
|
.typography(.caption)
|
|
.foregroundStyle(AppTextColors.tertiary)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.top, Design.Spacing.small)
|
|
}
|
|
|
|
// Motivational message
|
|
Text(String(localized: "Enjoy this moment. Your next ritual will appear when it's time."))
|
|
.typography(.caption)
|
|
.foregroundStyle(AppTextColors.tertiary)
|
|
.multilineTextAlignment(.center)
|
|
.padding(.top, Design.Spacing.small)
|
|
}
|
|
.padding(Design.Spacing.large)
|
|
.frame(maxWidth: .infinity)
|
|
.background(AppSurface.card)
|
|
.clipShape(.rect(cornerRadius: Design.CornerRadius.large))
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
TodayNoRitualsForTimeView(store: RitualStore.preview)
|
|
.padding()
|
|
.background(AppSurface.primary)
|
|
}
|