/**
* TabataFit Profile Screen — Premium React Native
* Apple Fitness+ inspired design, pure React Native components
*/
import { useRouter } from 'expo-router'
import {
View,
ScrollView,
StyleSheet,
TouchableOpacity,
Switch,
Text as RNText,
TextStyle,
} from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import * as Linking from 'expo-linking'
import Constants from 'expo-constants'
import { useTranslation } from 'react-i18next'
import { useMemo } from 'react'
import { useUserStore } from '@/src/shared/stores'
import { requestNotificationPermissions, usePurchases } from '@/src/shared/hooks'
import { useThemeColors, BRAND } from '@/src/shared/theme'
import type { ThemeColors } from '@/src/shared/theme/types'
// ═══════════════════════════════════════════════════════════════════════════
// STYLED TEXT COMPONENT
// ═══════════════════════════════════════════════════════════════════════════
interface TextProps {
children: React.ReactNode
style?: TextStyle
size?: number
weight?: 'normal' | 'bold' | '600' | '700' | '800' | '900'
color?: string
center?: boolean
}
function Text({ children, style, size, weight, color, center }: TextProps) {
const colors = useThemeColors()
return (
{children}
)
}
// ═══════════════════════════════════════════════════════════════════════════
// COMPONENT: PROFILE SCREEN
// ═══════════════════════════════════════════════════════════════════════════
export default function ProfileScreen() {
const { t } = useTranslation('screens')
const router = useRouter()
const insets = useSafeAreaInsets()
const colors = useThemeColors()
const styles = useMemo(() => createStyles(colors), [colors])
const profile = useUserStore((s) => s.profile)
const settings = useUserStore((s) => s.settings)
const updateSettings = useUserStore((s) => s.updateSettings)
const updateProfile = useUserStore((s) => s.updateProfile)
const { restorePurchases, isPremium } = usePurchases()
const planLabel = isPremium ? 'TabataFit+' : t('profile.freePlan')
const avatarInitial = profile.name?.[0]?.toUpperCase() || 'U'
// Mock stats (replace with real data from activityStore when available)
const stats = {
workouts: 47,
streak: 12,
calories: 12500,
}
const handleSignOut = () => {
updateProfile({
name: '',
email: '',
subscription: 'free',
onboardingCompleted: false,
})
router.replace('/onboarding')
}
const handleRestore = async () => {
await restorePurchases()
}
const handleReminderToggle = async (enabled: boolean) => {
if (enabled) {
const granted = await requestNotificationPermissions()
if (!granted) return
}
updateSettings({ reminders: enabled })
}
const handleRateApp = () => {
Linking.openURL('https://apps.apple.com/app/tabatafit/id1234567890')
}
const handleContactUs = () => {
Linking.openURL('mailto:contact@tabatafit.app')
}
const handlePrivacyPolicy = () => {
router.push('/privacy')
}
const handleFAQ = () => {
Linking.openURL('https://tabatafit.app/faq')
}
// App version
const appVersion = Constants.expoConfig?.version ?? '1.0.0'
return (
{/* ════════════════════════════════════════════════════════════════════
PROFILE HEADER CARD
═══════════════════════════════════════════════════════════════════ */}
{/* Avatar with gradient background */}
{avatarInitial}
{/* Name & Plan */}
{profile.name || t('profile.guest')}
{planLabel}
{isPremium && (
✓
)}
{/* Stats Row */}
🔥 {stats.workouts}
{t('profile.statsWorkouts')}
📅 {stats.streak}
{t('profile.statsStreak')}
⚡️ {Math.round(stats.calories / 1000)}k
{t('profile.statsCalories')}
{/* ════════════════════════════════════════════════════════════════════
UPGRADE CTA (FREE USERS ONLY)
═══════════════════════════════════════════════════════════════════ */}
{!isPremium && (
router.push('/paywall')}
>
✨ {t('profile.upgradeTitle')}
{t('profile.upgradeDescription')}
{t('profile.learnMore')} →
)}
{/* ════════════════════════════════════════════════════════════════════
WORKOUT SETTINGS
═══════════════════════════════════════════════════════════════════ */}
{t('profile.sectionWorkout')}
{t('profile.hapticFeedback')}
updateSettings({ haptics: v })}
trackColor={{ false: colors.bg.overlay1, true: BRAND.PRIMARY }}
thumbColor="#FFFFFF"
/>
{t('profile.soundEffects')}
updateSettings({ soundEffects: v })}
trackColor={{ false: colors.bg.overlay1, true: BRAND.PRIMARY }}
thumbColor="#FFFFFF"
/>
{t('profile.voiceCoaching')}
updateSettings({ voiceCoaching: v })}
trackColor={{ false: colors.bg.overlay1, true: BRAND.PRIMARY }}
thumbColor="#FFFFFF"
/>
{/* ════════════════════════════════════════════════════════════════════
NOTIFICATIONS
═══════════════════════════════════════════════════════════════════ */}
{t('profile.sectionNotifications')}
{t('profile.dailyReminders')}
{settings.reminders && (
{t('profile.reminderTime')}
{settings.reminderTime}
)}
{/* ════════════════════════════════════════════════════════════════════
ABOUT
═══════════════════════════════════════════════════════════════════ */}
{t('profile.sectionAbout')}
{t('profile.version')}
{appVersion}
{t('profile.rateApp')}
›
{t('profile.contactUs')}
›
{t('profile.faq')}
›
{t('profile.privacyPolicy')}
›
{/* ════════════════════════════════════════════════════════════════════
ACCOUNT (PREMIUM USERS ONLY)
═══════════════════════════════════════════════════════════════════ */}
{isPremium && (
<>
{t('profile.sectionAccount')}
{t('profile.restorePurchases')}
›
>
)}
{/* ════════════════════════════════════════════════════════════════════
SIGN OUT
═══════════════════════════════════════════════════════════════════ */}
{t('profile.signOut')}
)
}
// ═══════════════════════════════════════════════════════════════════════════
// STYLES
// ═══════════════════════════════════════════════════════════════════════════
function createStyles(colors: ThemeColors) {
return StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.bg.base,
},
scrollView: {
flex: 1,
},
scrollContent: {
flexGrow: 1,
},
section: {
marginHorizontal: 16,
marginTop: 20,
backgroundColor: colors.bg.surface,
borderRadius: 10,
overflow: 'hidden',
},
sectionHeader: {
fontSize: 13,
fontWeight: '600',
color: colors.text.tertiary,
textTransform: 'uppercase',
marginLeft: 32,
marginTop: 20,
marginBottom: 8,
},
headerContainer: {
alignItems: 'center',
paddingVertical: 24,
paddingHorizontal: 16,
},
avatarContainer: {
width: 90,
height: 90,
borderRadius: 45,
backgroundColor: BRAND.PRIMARY,
justifyContent: 'center',
alignItems: 'center',
shadowColor: BRAND.PRIMARY,
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.5,
shadowRadius: 20,
elevation: 10,
},
nameContainer: {
marginTop: 16,
alignItems: 'center',
},
planContainer: {
flexDirection: 'row',
alignItems: 'center',
marginTop: 4,
gap: 4,
},
statsContainer: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 16,
gap: 32,
},
statItem: {
alignItems: 'center',
},
premiumContainer: {
paddingVertical: 16,
paddingHorizontal: 16,
},
premiumContent: {
gap: 4,
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 12,
paddingHorizontal: 16,
borderBottomWidth: 0.5,
borderBottomColor: colors.border.glassLight,
},
rowLast: {
borderBottomWidth: 0,
},
rowLabel: {
fontSize: 17,
color: colors.text.primary,
},
rowValue: {
fontSize: 17,
color: colors.text.tertiary,
},
rowTime: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 12,
paddingHorizontal: 16,
borderTopWidth: 0.5,
borderTopColor: colors.border.glassLight,
},
button: {
paddingVertical: 14,
alignItems: 'center',
},
destructive: {
fontSize: 17,
color: BRAND.DANGER,
},
signOutSection: {
marginTop: 20,
},
})
}