Andromida/Andromida/App/Views/Today/Components/TodayNoRitualsForTimeView.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)
}