226 lines
7.9 KiB
Swift
226 lines
7.9 KiB
Swift
import SwiftUI
|
|
|
|
// MARK: - Home View
|
|
|
|
struct HomeView: View {
|
|
@EnvironmentObject var appState: AppState
|
|
@State private var showPartnerHome = false
|
|
@State private var showBucketList = false
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: CloserSpacing.xl) {
|
|
// Welcome header
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text("Welcome back")
|
|
.font(CloserFont.callout)
|
|
.foregroundColor(.closerTextSecondary)
|
|
Text(appState.currentUser?.displayName ?? "Partner")
|
|
.font(CloserFont.title1)
|
|
.foregroundColor(.closerText)
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.closerPadding()
|
|
|
|
// Streak card
|
|
StreakCard()
|
|
.closerPadding()
|
|
|
|
// Quick actions
|
|
VStack(alignment: .leading, spacing: CloserSpacing.md) {
|
|
Text("Today")
|
|
.closerSectionTitle()
|
|
.closerPadding()
|
|
|
|
ScrollView(.horizontal, showsIndicators: false) {
|
|
HStack(spacing: CloserSpacing.md) {
|
|
QuickActionCard(
|
|
icon: "heart.fill",
|
|
title: "Daily Question",
|
|
subtitle: "Connect with your partner",
|
|
color: .closerPrimary
|
|
)
|
|
|
|
QuickActionCard(
|
|
icon: "gamecontroller.fill",
|
|
title: "Play Together",
|
|
subtitle: "Games & challenges",
|
|
color: .closerSecondary
|
|
)
|
|
|
|
QuickActionCard(
|
|
icon: "sparkles",
|
|
title: "Date Ideas",
|
|
subtitle: "Plan something fun",
|
|
color: .closerGold
|
|
)
|
|
}
|
|
.padding(.horizontal, CloserSpacing.xl)
|
|
}
|
|
}
|
|
|
|
// Partner status
|
|
VStack(alignment: .leading, spacing: CloserSpacing.sm) {
|
|
Text("Partner")
|
|
.closerSectionTitle()
|
|
.closerPadding()
|
|
|
|
PartnerStatusRow(
|
|
displayName: "Your Partner",
|
|
answered: false,
|
|
lastActive: nil
|
|
)
|
|
.closerPadding()
|
|
}
|
|
|
|
// Relationship summary
|
|
VStack(alignment: .leading, spacing: CloserSpacing.sm) {
|
|
Text("Your Journey")
|
|
.closerSectionTitle()
|
|
.closerPadding()
|
|
|
|
VStack(spacing: CloserSpacing.sm) {
|
|
StatRow(icon: "flame.fill", label: "Streak", value: "\(appState.currentCouple?.streakCount ?? 0) days")
|
|
StatRow(icon: "questionmark.bubble.fill", label: "Questions Answered", value: "12")
|
|
StatRow(icon: "gamecontroller.fill", label: "Games Played", value: "5")
|
|
}
|
|
.closerPadding()
|
|
}
|
|
|
|
// Bottom nav to partner home
|
|
Button(action: { showPartnerHome = true }) {
|
|
Label("View Partner's Activity", systemImage: "person.fill")
|
|
}
|
|
.buttonStyle(SecondaryButtonStyle())
|
|
.closerPadding()
|
|
|
|
Spacer()
|
|
.frame(height: CloserSpacing.xxl)
|
|
}
|
|
}
|
|
.background(Color.closerBackground)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.navigationDestination(isPresented: $showPartnerHome) {
|
|
PartnerHomeView()
|
|
}
|
|
.navigationDestination(isPresented: $showBucketList) {
|
|
BucketListView()
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Partner Home
|
|
|
|
struct PartnerHomeView: View {
|
|
@Environment(\.dismiss) private var dismiss
|
|
|
|
var body: some View {
|
|
ScrollView {
|
|
VStack(spacing: CloserSpacing.xl) {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text("Partner's Activity")
|
|
.font(CloserFont.title1)
|
|
.foregroundColor(.closerText)
|
|
Text("See what your partner has been up to")
|
|
.font(CloserFont.callout)
|
|
.foregroundColor(.closerTextSecondary)
|
|
}
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
.closerPadding()
|
|
|
|
EmptyStateView(
|
|
icon: "person.crop.circle.badge.questionmark",
|
|
title: "No Recent Activity",
|
|
message: "Activity updates will appear here when your partner answers questions or plays games."
|
|
)
|
|
}
|
|
}
|
|
.background(Color.closerBackground)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
}
|
|
}
|
|
|
|
// MARK: - Subviews
|
|
|
|
struct StreakCard: View {
|
|
@EnvironmentObject var appState: AppState
|
|
|
|
var body: some View {
|
|
HStack {
|
|
VStack(alignment: .leading, spacing: 4) {
|
|
Text("Couple Streak")
|
|
.font(CloserFont.subheadline)
|
|
.foregroundColor(.closerTextSecondary)
|
|
HStack(spacing: 8) {
|
|
Image(systemName: "flame.fill")
|
|
.foregroundColor(.closerDanger)
|
|
Text("\(appState.currentCouple?.streakCount ?? 0) days")
|
|
.font(CloserFont.title2)
|
|
.foregroundColor(.closerText)
|
|
}
|
|
}
|
|
Spacer()
|
|
|
|
// Streak dots
|
|
HStack(spacing: 6) {
|
|
ForEach(0..<7) { i in
|
|
Circle()
|
|
.fill(i < (appState.currentCouple?.streakCount ?? 0) % 7 ? Color.closerDanger : Color.closerDivider)
|
|
.frame(width: 12, height: 12)
|
|
}
|
|
}
|
|
}
|
|
.padding(CloserSpacing.lg)
|
|
.closerCard()
|
|
}
|
|
}
|
|
|
|
struct QuickActionCard: View {
|
|
let icon: String
|
|
let title: String
|
|
let subtitle: String
|
|
let color: Color
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: CloserSpacing.sm) {
|
|
Image(systemName: icon)
|
|
.font(.title2)
|
|
.foregroundColor(color)
|
|
|
|
Text(title)
|
|
.font(CloserFont.headline)
|
|
.foregroundColor(.closerText)
|
|
|
|
Text(subtitle)
|
|
.font(CloserFont.caption)
|
|
.foregroundColor(.closerTextSecondary)
|
|
}
|
|
.padding(CloserSpacing.lg)
|
|
.frame(width: 160, alignment: .leading)
|
|
.closerCard()
|
|
}
|
|
}
|
|
|
|
struct StatRow: View {
|
|
let icon: String
|
|
let label: String
|
|
let value: String
|
|
|
|
var body: some View {
|
|
HStack {
|
|
Image(systemName: icon)
|
|
.foregroundColor(.closerPrimary)
|
|
.frame(width: 24)
|
|
Text(label)
|
|
.font(CloserFont.callout)
|
|
.foregroundColor(.closerText)
|
|
Spacer()
|
|
Text(value)
|
|
.font(CloserFont.headline)
|
|
.foregroundColor(.closerText)
|
|
}
|
|
.padding(CloserSpacing.md)
|
|
.background(Color.closerSurface)
|
|
.cornerRadius(CloserRadius.medium)
|
|
}
|
|
} |