Andromida/AndromidaWidget/Views/Components/LargeWidgetView.swift

86 lines
3.9 KiB
Swift

import SwiftUI
import WidgetKit
import Bedrock
struct LargeWidgetView: View {
let entry: WidgetEntry
var body: some View {
VStack(alignment: .leading, spacing: Design.Spacing.large) {
HStack {
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
Text(String(localized: "Today's Progress"))
.styled(.heading, emphasis: .custom(AppTextColors.primary))
Text("\(entry.currentStreak) day streak")
.styled(.subheading, emphasis: .custom(AppAccent.primary))
}
Spacer()
ZStack {
Circle()
.stroke(AppTextColors.primary.opacity(0.1), lineWidth: 6)
Circle()
.trim(from: 0, to: entry.completionRate)
.stroke(AppAccent.primary, style: StrokeStyle(lineWidth: 6, lineCap: .round))
.rotationEffect(.degrees(-90))
Text("\(Int(entry.completionRate * 100))%")
.styled(.captionEmphasis, emphasis: .custom(AppTextColors.primary))
}
.frame(width: 50, height: 50)
}
.padding(.top, Design.Spacing.small)
Divider()
.background(AppTextColors.primary.opacity(0.2))
.padding(.vertical, Design.Spacing.small)
if entry.nextHabits.isEmpty {
WidgetEmptyStateView(
iconSize: .section,
title: String(localized: "No rituals scheduled for \(entry.currentTimeOfDay.lowercased())."),
subtitle: entry.currentTimeOfDay,
symbolName: entry.currentTimeOfDaySymbol,
timeRange: entry.currentTimeOfDayRange,
nextRitual: entry.nextRitualInfo,
isCompact: false
)
} else {
VStack(alignment: .leading, spacing: Design.Spacing.small) {
Text(String(localized: "Habits"))
.styled(.captionEmphasis, emphasis: .custom(AppTextColors.secondary))
VStack(spacing: Design.Spacing.medium) {
ForEach(entry.nextHabits) { habit in
HStack(spacing: Design.Spacing.medium) {
Image(systemName: habit.symbolName)
.foregroundColor(AppAccent.primary)
.font(.system(size: 18))
.frame(width: 24)
VStack(alignment: .leading, spacing: Design.Spacing.xSmall) {
Text(habit.title)
.styled(.subheading, emphasis: .custom(AppTextColors.primary))
.lineLimit(1)
Text(habit.ritualTitle)
.styled(.caption, emphasis: .custom(AppTextColors.tertiary))
.lineLimit(1)
}
Spacer()
Image(systemName: habit.isCompleted ? "checkmark.circle.fill" : "circle")
.foregroundColor(habit.isCompleted ? .green : AppTextColors.primary.opacity(0.2))
.font(.system(size: 20))
}
}
}
}
}
Spacer()
}
.padding(Design.Spacing.large)
.containerBackground(for: .widget) {
AppSurface.primary
}
}
}