Files
Reflect/Shared/Views/SharingTemplates/Variations/MonthTotalVariations.swift
Trey t 0442eab1f8 Rebrand entire project from Feels to Reflect
Complete rename across all bundle IDs, App Groups, CloudKit containers,
StoreKit product IDs, data store filenames, URL schemes, logger subsystems,
Swift identifiers, user-facing strings (7 languages), file names, directory
names, Xcode project, schemes, assets, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 11:47:16 -06:00

222 lines
7.9 KiB
Swift

//
// MonthTotalVariations.swift
// Reflect
//
// 3 design variations for the Month Total sharing template.
//
import SwiftUI
// MARK: - V1 "Clean Calendar" Calendar-style grid, Health-app feel
struct MonthTotalV1: View {
let moodMetrics: [MoodMetrics]
let moodEntries: [MoodEntryModel]
let month: Int
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults)
private var moodTint: MoodTints = .Default
let columns = Array(repeating: GridItem(.flexible(), spacing: 8), count: 7)
var image: UIImage {
shareView.asImage(size: CGSize(width: 666, height: 1190))
}
var shareView: some View {
ZStack {
Color.white
VStack(spacing: 0) {
Spacer().frame(height: 70)
// Header
VStack(spacing: 8) {
Text(Random.monthName(fromMonthInt: month))
.font(.system(size: 36, weight: .bold, design: .rounded))
.foregroundColor(Color(hex: "1C1C1E"))
Text("\(moodEntries.count) DAYS TRACKED")
.font(.system(size: 14, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "8E8E93"))
.tracking(2)
}
Spacer().frame(height: 40)
// Calendar grid
LazyVGrid(columns: columns, spacing: 8) {
ForEach(moodEntries) { entry in
RoundedRectangle(cornerRadius: 10)
.fill(moodTint.color(forMood: entry.mood))
.frame(height: 70)
.overlay(
VStack(spacing: 4) {
entry.mood.icon
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 20)
.foregroundColor(.white)
Text(DateFormattingCache.shared.string(for: entry.forDate ?? Date(), format: .day))
.font(.system(size: 12, weight: .semibold, design: .rounded))
.foregroundColor(.white.opacity(0.8))
}
)
}
}
.padding(.horizontal, 32)
Spacer().frame(height: 40)
// Stats row
HStack(spacing: 0) {
ForEach(moodMetrics.sorted(by: { $0.mood.rawValue > $1.mood.rawValue }), id: \.mood) { metric in
VStack(spacing: 8) {
Capsule()
.fill(moodTint.color(forMood: metric.mood))
.frame(width: 40, height: 6)
Text("\(metric.percent, specifier: "%.0f")%")
.font(.system(size: 18, weight: .bold, design: .rounded))
.foregroundColor(Color(hex: "1C1C1E"))
Text(metric.mood.strValue)
.font(.system(size: 11, weight: .medium))
.foregroundColor(Color(hex: "8E8E93"))
}
.frame(maxWidth: .infinity)
}
}
.padding(.horizontal, 24)
Spacer()
VStack(spacing: 10) {
Image("ReflectAppIcon")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 96, height: 96)
.clipShape(RoundedRectangle(cornerRadius: 22))
Text("Reflect")
.font(.system(size: 28, weight: .medium, design: .rounded))
.foregroundColor(Color(hex: "C7C7CC"))
}
Spacer().frame(height: 50)
}
}
.frame(width: 666, height: 1190)
}
var body: some View { shareView }
}
// MARK: - V5 "Stacked Bars" Full-width mood color bars, white overlays
struct MonthTotalV5: View {
let moodMetrics: [MoodMetrics]
let moodEntries: [MoodEntryModel]
let month: Int
@AppStorage(UserDefaultsStore.Keys.moodTint.rawValue, store: GroupUserDefaults.groupDefaults)
private var moodTint: MoodTints = .Default
let columns = Array(repeating: GridItem(.flexible(), spacing: 3), count: 7)
var image: UIImage {
shareView.asImage(size: CGSize(width: 666, height: 1190))
}
var shareView: some View {
let sorted = moodMetrics.sorted(by: { $0.mood.rawValue > $1.mood.rawValue })
return VStack(spacing: 0) {
// Header dark band
ZStack {
Color(hex: "1C1C1E")
HStack {
Text(Random.monthName(fromMonthInt: month).uppercased())
.font(.system(size: 18, weight: .heavy, design: .rounded))
.foregroundColor(.white)
.tracking(4)
Spacer()
Text("\(moodEntries.count)")
.font(.system(size: 28, weight: .heavy, design: .rounded))
.foregroundColor(.white)
}
.padding(.horizontal, 32)
}
.frame(height: 80)
// Mini grid of all days
ZStack {
Color(hex: "1C1C1E")
LazyVGrid(columns: columns, spacing: 3) {
ForEach(moodEntries) { entry in
Rectangle()
.fill(moodTint.color(forMood: entry.mood))
.frame(height: 50)
}
}
.padding(24)
}
// Color percentage blocks
ForEach(sorted, id: \.mood) { metric in
let barHeight: CGFloat = max(CGFloat(metric.percent / 100) * 400, 50)
ZStack {
moodTint.color(forMood: metric.mood)
HStack {
VStack(alignment: .leading, spacing: 2) {
Text(metric.mood.strValue.uppercased())
.font(.system(size: 13, weight: .bold, design: .rounded))
.tracking(2)
Text("\(metric.total) days")
.font(.system(size: 11, weight: .medium))
.opacity(0.7)
}
Spacer()
Text("\(metric.percent, specifier: "%.0f")%")
.font(.system(size: 32, weight: .heavy, design: .rounded))
}
.foregroundColor(.white)
.padding(.horizontal, 32)
}
.frame(height: barHeight)
}
// Footer dark band fills remaining space
ZStack {
Color(hex: "1C1C1E")
VStack(spacing: 10) {
Image("ReflectAppIcon")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 96, height: 96)
.clipShape(RoundedRectangle(cornerRadius: 22))
Text("Reflect")
.font(.system(size: 28, weight: .bold, design: .rounded))
.foregroundColor(.white.opacity(0.3))
}
}
.frame(maxHeight: .infinity)
}
.background(Color(hex: "1C1C1E"))
.frame(width: 666, height: 1190)
}
var body: some View { shareView }
}