Closer/iphone/Closer/Home/HomeViews.swift

245 lines
8.7 KiB
Swift

import SwiftUI
// MARK: - Home View
struct HomeView: View {
@EnvironmentObject var appState: AppState
@State private var showPartnerHome = false
@State private var showBucketList = false
@State private var showCreateInvite = false
@State private var showAcceptInvite = 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()
if appState.currentCouple == nil {
PartnerActivationCard(
onInvite: { showCreateInvite = true },
onAcceptInvite: { showAcceptInvite = true }
)
.closerPadding()
} else {
// 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)
}
}
if appState.currentCouple != nil {
// Partner status
VStack(alignment: .leading, spacing: CloserSpacing.sm) {
Text("Partner")
.closerSectionTitle()
.closerPadding()
PartnerStatusRow(
displayName: appState.currentPartner?.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()
}
.navigationDestination(isPresented: $showCreateInvite) {
CreateInviteView()
}
.navigationDestination(isPresented: $showAcceptInvite) {
AcceptInviteView()
}
}
}
// 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)
}
}