feat: Apple Watch app + Paywall + Privacy Policy + rebranding
## Major Features - Apple Watch companion app (6 phases complete) - WatchConnectivity iPhone ↔ Watch - HealthKit integration (HR, calories) - SwiftUI premium UI - 9 complication types - Always-On Display support - Paywall screen with RevenueCat integration - Privacy Policy screen - App rebranding: tabatago → TabataFit - Bundle ID: com.millianlmx.tabatafit ## Changes - New: ios/TabataFit Watch App/ (complete Watch app) - New: app/paywall.tsx (subscription UI) - New: app/privacy.tsx (privacy policy) - New: src/features/watch/ (Watch sync hooks) - New: admin-web/ (admin dashboard) - Updated: app.json, package.json (branding) - Updated: profile.tsx (paywall + privacy links) - Updated: i18n translations (EN/FR/DE/ES) - New: app icon 1024x1024 ## Watch App Files - TabataFitWatchApp.swift (entry point) - ContentView.swift (premium UI) - HealthKitManager.swift (HR + calories) - WatchSessionManager.swift (communication) - Complications/ (WidgetKit) - UserDefaults+Shared.swift (data sharing)
This commit is contained in:
@@ -29,7 +29,7 @@ import type { ThemeColors } from '@/src/shared/theme/types'
|
||||
import { SPACING, LAYOUT } from '@/src/shared/constants/spacing'
|
||||
import { RADIUS } from '@/src/shared/constants/borderRadius'
|
||||
import { DURATION, EASE, SPRING } from '@/src/shared/constants/animations'
|
||||
import { track } from '@/src/shared/services/analytics'
|
||||
import { track, identifyUser, setUserProperties, trackScreen } from '@/src/shared/services/analytics'
|
||||
|
||||
import type { FitnessLevel, FitnessGoal, WeeklyFrequency } from '@/src/shared/types'
|
||||
|
||||
@@ -938,25 +938,43 @@ export default function OnboardingScreen() {
|
||||
|
||||
// Track onboarding_started + first step viewed on mount
|
||||
useEffect(() => {
|
||||
trackScreen('onboarding')
|
||||
track('onboarding_started')
|
||||
track('onboarding_step_viewed', { step: 1, step_name: STEP_NAMES[1] })
|
||||
}, [])
|
||||
|
||||
const finishOnboarding = useCallback(
|
||||
(plan: 'free' | 'premium-monthly' | 'premium-yearly') => {
|
||||
const totalTime = Date.now() - onboardingStartTime.current
|
||||
|
||||
track('onboarding_completed', {
|
||||
plan,
|
||||
total_time_ms: Date.now() - onboardingStartTime.current,
|
||||
total_time_ms: totalTime,
|
||||
steps_completed: step,
|
||||
})
|
||||
|
||||
completeOnboarding({
|
||||
const userData = {
|
||||
name: name.trim() || 'Athlete',
|
||||
fitnessLevel: level,
|
||||
goal,
|
||||
weeklyFrequency: frequency,
|
||||
barriers,
|
||||
}
|
||||
|
||||
completeOnboarding(userData)
|
||||
|
||||
// Identify user in PostHog for session replay linking
|
||||
const userId = `user_${Date.now()}` // In production, use actual user ID from backend
|
||||
identifyUser(userId, {
|
||||
name: userData.name,
|
||||
fitness_level: level,
|
||||
fitness_goal: goal,
|
||||
weekly_frequency: frequency,
|
||||
subscription_plan: plan,
|
||||
onboarding_completed_at: new Date().toISOString(),
|
||||
barriers: barriers.join(','),
|
||||
})
|
||||
|
||||
if (plan !== 'free') {
|
||||
setSubscription(plan)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user