/** * TabataFit Home Screen * React Native UI — wired to shared data */ import { View, StyleSheet, ScrollView, Pressable, Dimensions, Text as RNText, Image as RNImage } 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 } from 'react' import { useHaptics } from '@/src/shared/hooks' import { useUserStore, useActivityStore } from '@/src/shared/stores' import { getFeaturedWorkouts, getPopularWorkouts, getTrainerById, COLLECTIONS, WORKOUTS, } from '@/src/shared/data' import { StyledText } from '@/src/shared/components/StyledText' import { BRAND, DARK, TEXT, GLASS, SHADOW, GRADIENTS, } from '@/src/shared/constants/colors' import { SPACING, LAYOUT } from '@/src/shared/constants/spacing' import { RADIUS } from '@/src/shared/constants/borderRadius' const { width: SCREEN_WIDTH } = Dimensions.get('window') const CARD_WIDTH = SCREEN_WIDTH - LAYOUT.SCREEN_PADDING * 2 const FONTS = { LARGE_TITLE: 34, TITLE: 28, TITLE_2: 22, HEADLINE: 17, BODY: 17, SUBHEADLINE: 15, CAPTION_1: 12, CAPTION_2: 11, } // ═══════════════════════════════════════════════════════════════════════════ // HELPERS // ═══════════════════════════════════════════════════════════════════════════ function getGreeting() { const hour = new Date().getHours() if (hour < 12) return 'Good morning' if (hour < 18) return 'Good afternoon' return 'Good evening' } function PrimaryButton({ children, onPress }: { children: string; onPress?: () => void }) { return ( {children} ) } function PlainButton({ children, onPress }: { children: string; onPress?: () => void }) { return ( {children} ) } // ═══════════════════════════════════════════════════════════════════════════ // MAIN SCREEN // ═══════════════════════════════════════════════════════════════════════════ export default function HomeScreen() { const insets = useSafeAreaInsets() const router = useRouter() const haptics = useHaptics() const userName = useUserStore((s) => s.profile.name) const history = useActivityStore((s) => s.history) const recentWorkouts = useMemo(() => history.slice(0, 3), [history]) const featured = getFeaturedWorkouts()[0] ?? WORKOUTS[0] const featuredTrainer = getTrainerById(featured.trainerId) const popular = getPopularWorkouts(4) const handleWorkoutPress = (id: string) => { haptics.buttonTap() router.push(`/workout/${id}`) } return ( {/* Header */} {getGreeting() + ', ' + userName} {/* Featured */} handleWorkoutPress(featured.id)} > {featured.thumbnailUrl ? ( ) : ( )} 🔥 FEATURED {featured.title} {featured.duration + ' min • ' + featured.level + ' • ' + (featuredTrainer?.name ?? '')} handleWorkoutPress(featured.id)}>START {/* Continue Watching — from activity store */} {recentWorkouts.length > 0 && ( Recent See All {recentWorkouts.map((result) => { const workout = WORKOUTS.find(w => w.id === result.workoutId) if (!workout) return null const trainer = getTrainerById(workout.trainerId) return ( handleWorkoutPress(result.workoutId)} > {trainer?.name[0] ?? 'T'} {workout.title} {result.calories + ' cal • ' + result.durationMinutes + ' min'} ) })} )} {/* Popular This Week */} Popular This Week {popular.map((item) => ( handleWorkoutPress(item.id)} > {item.title} {item.duration + ' min'} ))} {/* Collections */} Collections {COLLECTIONS.map((item) => ( { haptics.buttonTap(); router.push(`/collection/${item.id}`) }}> {item.icon} {item.title} {item.workoutIds.length + ' workouts • ' + item.description} ))} ) } // ═══════════════════════════════════════════════════════════════════════════ // STYLES // ═══════════════════════════════════════════════════════════════════════════ const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: DARK.BASE, }, scrollView: { flex: 1, }, scrollContent: { paddingHorizontal: LAYOUT.SCREEN_PADDING, }, // Header header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: SPACING[6], }, profileButton: { width: 40, height: 40, alignItems: 'center', justifyContent: 'center', }, // Buttons primaryButton: { flexDirection: 'row', alignItems: 'center', backgroundColor: BRAND.PRIMARY, paddingHorizontal: SPACING[4], paddingVertical: SPACING[3], borderRadius: RADIUS.SM, }, buttonIcon: { marginRight: SPACING[2], }, primaryButtonText: { fontSize: 14, fontWeight: '600', color: TEXT.PRIMARY, }, plainButtonText: { fontSize: FONTS.BODY, color: BRAND.PRIMARY, }, // Featured featuredCard: { width: CARD_WIDTH, height: 220, borderRadius: RADIUS.GLASS_CARD, overflow: 'hidden', marginBottom: SPACING[8], ...SHADOW.lg, }, featuredBadge: { position: 'absolute', top: SPACING[4], left: SPACING[4], backgroundColor: 'rgba(255, 255, 255, 0.15)', paddingHorizontal: SPACING[3], paddingVertical: SPACING[1], borderRadius: RADIUS.SM, borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.2)', }, featuredBadgeText: { fontSize: 11, fontWeight: 'bold', color: TEXT.PRIMARY, }, featuredContent: { position: 'absolute', bottom: 0, left: 0, right: 0, padding: SPACING[5], }, featuredButtons: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3], marginTop: SPACING[4], }, saveButton: { width: 44, height: 44, alignItems: 'center', justifyContent: 'center', backgroundColor: 'rgba(255, 255, 255, 0.1)', borderRadius: 22, borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.15)', }, // Sections section: { marginBottom: SPACING[8], }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: SPACING[4], }, horizontalScroll: { gap: SPACING[3], }, // Continue Card continueCard: { width: 140, }, continueThumb: { width: 140, height: 200, borderRadius: RADIUS.LG, overflow: 'hidden', alignItems: 'center', justifyContent: 'center', marginBottom: SPACING[2], }, // Popular Card popularCard: { width: 120, }, popularThumb: { width: 120, height: 120, borderRadius: RADIUS.LG, alignItems: 'center', justifyContent: 'center', marginBottom: SPACING[2], borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.1)', backgroundColor: 'rgba(255, 255, 255, 0.05)', }, // Collection Card collectionCard: { height: 80, borderRadius: RADIUS.LG, overflow: 'hidden', marginBottom: SPACING[3], borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.1)', }, collectionContent: { flex: 1, flexDirection: 'row', alignItems: 'center', paddingHorizontal: SPACING[5], }, collectionIcon: { fontSize: 28, marginRight: SPACING[4], }, collectionText: { flex: 1, }, })