Andromida/Andromida/App/Views/Rituals/Components/RitualMilestonesView.swift

75 lines
2.5 KiB
Swift

//
// RitualMilestonesView.swift
// Andromida
//
// Displays milestone achievements for a ritual journey.
//
import SwiftUI
import Bedrock
/// A view showing milestone achievements for a ritual.
struct RitualMilestonesView: View {
let milestones: [Milestone]
var body: some View {
VStack(alignment: .leading, spacing: Design.Spacing.small) {
Text(String(localized: "Milestones"))
.font(.headline)
.foregroundStyle(AppTextColors.primary)
HStack(spacing: Design.Spacing.small) {
ForEach(milestones) { milestone in
milestoneItem(milestone)
}
}
}
.padding(Design.Spacing.large)
.frame(maxWidth: .infinity, alignment: .leading)
.background(AppSurface.card)
.clipShape(.rect(cornerRadius: Design.CornerRadius.large))
}
private func milestoneItem(_ milestone: Milestone) -> some View {
VStack(spacing: Design.Spacing.xSmall) {
ZStack {
Circle()
.fill(milestone.isAchieved ? AppStatus.success.opacity(Design.Opacity.medium) : AppSurface.secondary)
.frame(width: AppMetrics.Size.milestoneIcon, height: AppMetrics.Size.milestoneIcon)
Image(systemName: milestone.symbolName)
.font(.caption)
.foregroundStyle(milestone.isAchieved ? AppStatus.success : AppTextColors.tertiary)
}
Text("Day \(milestone.day)")
.font(.caption2)
.foregroundStyle(milestone.isAchieved ? AppTextColors.primary : AppTextColors.tertiary)
Text(milestone.title)
.font(.caption2)
.foregroundStyle(milestone.isAchieved ? AppTextColors.secondary : AppTextColors.tertiary)
.lineLimit(1)
.minimumScaleFactor(0.8)
}
.frame(maxWidth: .infinity)
.accessibilityElement(children: .combine)
.accessibilityLabel("\(milestone.title), Day \(milestone.day)")
.accessibilityValue(milestone.isAchieved ? String(localized: "Achieved") : String(localized: "Not yet achieved"))
}
}
// MARK: - AppMetrics Extension
extension AppMetrics.Size {
static let milestoneIcon: CGFloat = 36
}
#Preview {
VStack {
RitualMilestonesView(milestones: Milestone.standardMilestones(currentDay: 10, totalDays: 28))
}
.padding(Design.Spacing.large)
.background(AppSurface.primary)
}