/** * TabataFit Home Screen - Premium Redesign * React Native UI with glassmorphism */ import { View, StyleSheet, ScrollView, Pressable, Dimensions, Text as RNText } from 'react-native' import { useRouter } from 'expo-router' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { LinearGradient } from 'expo-linear-gradient' import { BlurView } from 'expo-blur' import Ionicons from '@expo/vector-icons/Ionicons' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { useHaptics, useFeaturedWorkouts, usePopularWorkouts, useCollections } from '@/src/shared/hooks' import { useUserStore, useActivityStore } from '@/src/shared/stores' import { StyledText } from '@/src/shared/components/StyledText' import { WorkoutCard } from '@/src/shared/components/WorkoutCard' import { CollectionCard } from '@/src/shared/components/CollectionCard' import { WorkoutCardSkeleton, CollectionCardSkeleton, StatsCardSkeleton } from '@/src/shared/components/loading/Skeleton' import { useThemeColors, BRAND, GRADIENTS } from '@/src/shared/theme' import type { ThemeColors } from '@/src/shared/theme/types' import { SPACING, LAYOUT } from '@/src/shared/constants/spacing' import { RADIUS } from '@/src/shared/constants/borderRadius' import type { WorkoutCategory } from '@/src/shared/types' const { width: SCREEN_WIDTH } = Dimensions.get('window') const FONTS = { LARGE_TITLE: 34, TITLE: 28, TITLE_2: 22, HEADLINE: 17, SUBHEADLINE: 15, CAPTION_1: 12, CAPTION_2: 11, } const CATEGORIES: { id: WorkoutCategory | 'all'; key: string }[] = [ { id: 'all', key: 'all' }, { id: 'full-body', key: 'fullBody' }, { id: 'core', key: 'core' }, { id: 'upper-body', key: 'upperBody' }, { id: 'lower-body', key: 'lowerBody' }, { id: 'cardio', key: 'cardio' }, ] // ═══════════════════════════════════════════════════════════════════════════ // MAIN SCREEN // ═══════════════════════════════════════════════════════════════════════════ export default function HomeScreen() { const { t } = useTranslation() const insets = useSafeAreaInsets() const router = useRouter() const haptics = useHaptics() const colors = useThemeColors() const styles = useMemo(() => createStyles(colors), [colors]) const userName = useUserStore((s) => s.profile.name) const history = useActivityStore((s) => s.history) const recentWorkouts = useMemo(() => history.slice(0, 3), [history]) const [selectedCategory, setSelectedCategory] = useState('all') // React Query hooks for live data const { data: featuredWorkouts = [], isLoading: isLoadingFeatured } = useFeaturedWorkouts() const { data: popularWorkouts = [], isLoading: isLoadingPopular } = usePopularWorkouts(6) const { data: collections = [], isLoading: isLoadingCollections } = useCollections() const featured = featuredWorkouts[0] const filteredWorkouts = useMemo(() => { if (selectedCategory === 'all') return popularWorkouts return popularWorkouts.filter((w) => w.category === selectedCategory) }, [popularWorkouts, selectedCategory]) const greeting = (() => { const hour = new Date().getHours() if (hour < 12) return t('greetings.morning') if (hour < 18) return t('greetings.afternoon') return t('greetings.evening') })() const handleWorkoutPress = (id: string) => { haptics.buttonTap() router.push(`/workout/${id}`) } const handleCollectionPress = (id: string) => { haptics.buttonTap() router.push(`/collection/${id}`) } return ( {/* Hero Section */} {greeting} {userName} {/* Featured Workout */} {t('screens:home.featured')} {isLoadingFeatured ? ( ) : featured ? ( handleWorkoutPress(featured.id)} /> ) : null} {/* Category Filter */} {CATEGORIES.map((cat) => ( { haptics.buttonTap() setSelectedCategory(cat.id) }} > {selectedCategory === cat.id && ( )} {t(`categories.${cat.key}`)} ))} {/* Popular Workouts - Horizontal */} {t('screens:home.popularThisWeek')} {t('seeAll')} {isLoadingPopular ? ( // Loading skeletons <> ) : ( filteredWorkouts.map((workout: any) => ( handleWorkoutPress(workout.id)} /> )) )} {/* Collections Grid */} {t('screens:home.collections')} {isLoadingCollections ? ( // Loading skeletons for collections <> ) : ( collections.map((collection) => ( handleCollectionPress(collection.id)} /> )) )} ) } // ═══════════════════════════════════════════════════════════════════════════ // STYLES // ═══════════════════════════════════════════════════════════════════════════ function createStyles(colors: ThemeColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bg.base, }, scrollView: { flex: 1, }, scrollContent: { paddingHorizontal: LAYOUT.SCREEN_PADDING, }, // Hero Section heroSection: { marginBottom: SPACING[6], }, heroHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: SPACING[2], }, heroTitle: { flex: 1, marginRight: SPACING[3], }, profileButton: { width: 44, height: 44, alignItems: 'center', justifyContent: 'center', }, // Sections section: { marginBottom: SPACING[8], }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: SPACING[4], }, // Categories categoriesScroll: { gap: SPACING[2], paddingRight: SPACING[4], }, categoryChip: { paddingHorizontal: SPACING[4], paddingVertical: SPACING[2], borderRadius: RADIUS.FULL, overflow: 'hidden', borderWidth: 1, borderColor: colors.border.glass, }, categoryChipActive: { borderColor: BRAND.PRIMARY, backgroundColor: `${BRAND.PRIMARY}30`, }, // Workouts Scroll workoutsScroll: { gap: SPACING[3], paddingRight: SPACING[4], }, // Collections Grid collectionsGrid: { flexDirection: 'row', flexWrap: 'wrap', gap: SPACING[3], }, }) }