- Add complete onboarding flow with 7 screens: Welcome, Name Residence, Value Props, Create Account, Verify Email, First Task, Subscription - Auto-create residence after email verification for "Start Fresh" users - Add predefined task templates (HVAC, Smoke Detectors, Lawn Care, Leaks) that create real tasks with today as due date - Add returning user login button on welcome screen - Update RootView to prioritize onboarding flow for first-time users - Use app icon asset instead of house.fill SF Symbol - Smooth slide transitions with fade-out for back navigation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
121 lines
4.1 KiB
Swift
121 lines
4.1 KiB
Swift
import SwiftUI
|
|
|
|
/// Screen 1: Welcome screen with Start Fresh / Join Existing options
|
|
struct OnboardingWelcomeView: View {
|
|
var onStartFresh: () -> Void
|
|
var onJoinExisting: () -> Void
|
|
var onLogin: () -> Void
|
|
|
|
@State private var showingLoginSheet = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
Spacer()
|
|
|
|
// Hero section
|
|
VStack(spacing: AppSpacing.xl) {
|
|
// App icon
|
|
Image("icon")
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(width: 120, height: 120)
|
|
.clipShape(RoundedRectangle(cornerRadius: AppRadius.xxl))
|
|
.shadow(color: Color.appPrimary.opacity(0.3), radius: 20, y: 10)
|
|
|
|
// Welcome text
|
|
VStack(spacing: AppSpacing.sm) {
|
|
Text("Welcome to Casera")
|
|
.font(.largeTitle)
|
|
.fontWeight(.bold)
|
|
.foregroundColor(Color.appTextPrimary)
|
|
|
|
Text("Your home maintenance companion")
|
|
.font(.title3)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
// Action buttons
|
|
VStack(spacing: AppSpacing.md) {
|
|
// Primary CTA - Start Fresh
|
|
Button(action: onStartFresh) {
|
|
HStack(spacing: AppSpacing.sm) {
|
|
Image("icon")
|
|
.resizable()
|
|
.scaledToFit()
|
|
.frame(width: 24, height: 24)
|
|
Text("Start Fresh")
|
|
.font(.headline)
|
|
.fontWeight(.semibold)
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.frame(height: 56)
|
|
.foregroundColor(Color.appTextOnPrimary)
|
|
.background(
|
|
LinearGradient(
|
|
colors: [Color.appPrimary, Color.appPrimary.opacity(0.8)],
|
|
startPoint: .topLeading,
|
|
endPoint: .bottomTrailing
|
|
)
|
|
)
|
|
.cornerRadius(AppRadius.md)
|
|
.shadow(color: Color.appPrimary.opacity(0.3), radius: 10, y: 5)
|
|
}
|
|
|
|
// Secondary CTA - Join Existing
|
|
Button(action: onJoinExisting) {
|
|
HStack(spacing: AppSpacing.sm) {
|
|
Image(systemName: "person.2.fill")
|
|
.font(.title3)
|
|
Text("I have a code to join")
|
|
.font(.headline)
|
|
.fontWeight(.medium)
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
.frame(height: 56)
|
|
.foregroundColor(Color.appPrimary)
|
|
.background(Color.appPrimary.opacity(0.1))
|
|
.cornerRadius(AppRadius.md)
|
|
}
|
|
|
|
// Returning user login
|
|
Button(action: {
|
|
showingLoginSheet = true
|
|
}) {
|
|
Text("Already have an account? Log in")
|
|
.font(.subheadline)
|
|
.foregroundColor(Color.appTextSecondary)
|
|
}
|
|
.padding(.top, AppSpacing.sm)
|
|
}
|
|
.padding(.horizontal, AppSpacing.xl)
|
|
.padding(.bottom, AppSpacing.xxxl)
|
|
}
|
|
.background(Color.appBackgroundPrimary)
|
|
.sheet(isPresented: $showingLoginSheet) {
|
|
LoginView(onLoginSuccess: {
|
|
showingLoginSheet = false
|
|
onLogin()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - Content-only version (no navigation bar)
|
|
|
|
/// Content-only version for use in coordinator
|
|
typealias OnboardingWelcomeContent = OnboardingWelcomeView
|
|
|
|
// MARK: - Preview
|
|
|
|
#Preview {
|
|
OnboardingWelcomeView(
|
|
onStartFresh: {},
|
|
onJoinExisting: {},
|
|
onLogin: {}
|
|
)
|
|
}
|