/** * TabataGo Profile Tab * User info, subscription status, quick stats. Settings via form sheet. */ import { useMemo } from 'react' import { View, Text, StyleSheet, ScrollView, Pressable } from 'react-native' import { useRouter } from 'expo-router' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useTranslation } from 'react-i18next' import { Icon } from '@/src/shared/components/Icon' import { useUserStore } from '@/src/shared/stores/userStore' import { useProgressStore } from '@/src/shared/stores/progressStore' import { usePurchases } from '@/src/shared/hooks' import { useThemeColors } from '@/src/shared/theme' import type { ThemeColors } from '@/src/shared/theme/types' import { TYPOGRAPHY } from '@/src/shared/constants/typography' import { SPACING, LAYOUT } from '@/src/shared/constants/spacing' import { RADIUS } from '@/src/shared/constants/borderRadius' import { GREEN, NAVY, TEXT, BORDER_COLORS } from '@/src/shared/constants/colors' export default function ProfileScreen() { const { t } = useTranslation() const router = useRouter() const insets = useSafeAreaInsets() const colors = useThemeColors() const styles = useMemo(() => createStyles(colors), [colors]) const profile = useUserStore(s => s.profile) const { isPremium } = usePurchases() const completedCount = useProgressStore(s => s.getCompletedCount()) const streak = useProgressStore(s => s.streak) const weeklyCount = useProgressStore(s => s.getWeeklyCount()) const avatarLetter = profile.name?.[0]?.toUpperCase() || '?' return ( {/* Avatar + name */} {avatarLetter} {profile.name || t('screens:profile.guest')} {isPremium ? t('screens:settings.premium') : t('screens:settings.free')} router.push('/settings')} hitSlop={8}> {/* Stats row */} {/* Upgrade banner (free users) */} {!isPremium && ( router.push('/paywall')} > {t('screens:profile.upgradeTitle')} {t('screens:profile.upgradeDescription')} )} {/* Settings link */} router.push('/settings')}> {t('screens:settings.title')} ) } function StatPill({ value, label, icon, color }: { value: number; label: string; icon: any; color: string }) { return ( {value} {label} ) } const pillStyles = StyleSheet.create({ pill: { flex: 1, alignItems: 'center', paddingVertical: SPACING[3], borderRadius: RADIUS.MD, borderWidth: 1, backgroundColor: NAVY[800], borderColor: BORDER_COLORS.DIM, gap: 4, }, value: { ...TYPOGRAPHY.TITLE_2, color: TEXT.PRIMARY, fontVariant: ['tabular-nums'] }, label: { ...TYPOGRAPHY.CAPTION_2, color: TEXT.TERTIARY, textAlign: 'center' }, }) function createStyles(colors: ThemeColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bg.base }, content: { paddingHorizontal: LAYOUT.SCREEN_PADDING }, profileHeader: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], marginBottom: SPACING[5], }, avatar: { width: 60, height: 60, borderRadius: 30, backgroundColor: NAVY[700] ?? NAVY[800], alignItems: 'center', justifyContent: 'center', borderWidth: 2, borderColor: BORDER_COLORS.DIM, }, avatarLetter: { ...TYPOGRAPHY.TITLE_1, color: TEXT.PRIMARY }, name: { ...TYPOGRAPHY.TITLE_2, color: TEXT.PRIMARY }, planBadge: { alignSelf: 'flex-start', marginTop: 4, paddingHorizontal: SPACING[2], paddingVertical: 2, borderRadius: RADIUS.SM, borderWidth: 1, }, planText: { ...TYPOGRAPHY.CAPTION_2, fontWeight: '600' }, statsRow: { flexDirection: 'row', gap: SPACING[2], marginBottom: SPACING[5] }, upgradeBanner: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], padding: SPACING[4], borderRadius: RADIUS.LG, borderWidth: 1, backgroundColor: colors.surface.default.backgroundColor, marginBottom: SPACING[3], borderCurve: 'continuous', }, upgradeTitle: { ...TYPOGRAPHY.HEADLINE, color: TEXT.PRIMARY }, upgradeDesc: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.SECONDARY, marginTop: 2 }, settingsRow: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], padding: SPACING[4], borderRadius: RADIUS.LG, borderWidth: 1, borderColor: BORDER_COLORS.DIM, backgroundColor: colors.surface.default.backgroundColor, borderCurve: 'continuous', }, settingsLabel: { ...TYPOGRAPHY.BODY, color: TEXT.PRIMARY, flex: 1 }, }) }