/** * TabataFit Collection Detail Screen * Shows collection info + list of workouts in that collection */ import { useMemo } from 'react' import { View, StyleSheet, ScrollView, Pressable } from 'react-native' import { useRouter, useLocalSearchParams } from 'expo-router' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { LinearGradient } from 'expo-linear-gradient' import { Icon } from '@/src/shared/components/Icon' import { useTranslation } from 'react-i18next' import { useHaptics } from '@/src/shared/hooks' import { useCollection } from '@/src/shared/hooks/useSupabaseData' import { getWorkoutById } from '@/src/shared/data' import { useTranslatedWorkouts } from '@/src/shared/data/useTranslatedData' import { StyledText } from '@/src/shared/components/StyledText' import { track } from '@/src/shared/services/analytics' 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' export default function CollectionDetailScreen() { const insets = useSafeAreaInsets() const router = useRouter() const haptics = useHaptics() const { t } = useTranslation() const { id } = useLocalSearchParams<{ id: string }>() const colors = useThemeColors() const styles = useMemo(() => createStyles(colors), [colors]) const { data: collection, isLoading } = useCollection(id) // Resolve workouts from collection's workoutIds const rawWorkouts = useMemo(() => { if (!collection) return [] return collection.workoutIds .map((wId) => getWorkoutById(wId)) .filter(Boolean) as NonNullable>[] }, [collection]) const workouts = useTranslatedWorkouts(rawWorkouts) const handleBack = () => { haptics.selection() router.back() } const handleWorkoutPress = (workoutId: string) => { haptics.buttonTap() track('collection_workout_tapped', { collection_id: id, workout_id: workoutId, }) router.push(`/workout/${workoutId}`) } if (isLoading) { return ( Loading... ) } if (!collection) { return ( Collection not found ) } return ( {/* Header */} {collection.title} {/* Hero Card */} {collection.icon} {collection.title} {collection.description} {t('plurals.workout', { count: workouts.length })} {/* Workout List */} {t('screens:explore.workouts')} {workouts.map((workout) => ( handleWorkoutPress(workout.id)} > {workout.title} {t('durationLevel', { duration: workout.duration, level: t(`levels.${(workout.level ?? 'Beginner').toLowerCase()}`), })} {t('units.calUnit', { count: workout.calories })} ))} {workouts.length === 0 && ( No workouts in this collection )} ) } function createStyles(colors: ThemeColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.bg.base, }, centered: { alignItems: 'center', justifyContent: 'center', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: LAYOUT.SCREEN_PADDING, paddingVertical: SPACING[3], }, backButton: { width: 44, height: 44, alignItems: 'center', justifyContent: 'center', }, heroCard: { height: 200, borderRadius: RADIUS.XL, overflow: 'hidden', ...colors.shadow.lg, }, heroContent: { flex: 1, padding: SPACING[5], justifyContent: 'flex-end', }, heroIcon: { marginBottom: SPACING[2], }, scrollView: { flex: 1, }, scrollContent: { paddingHorizontal: LAYOUT.SCREEN_PADDING, }, workoutCard: { flexDirection: 'row', alignItems: 'center', paddingVertical: SPACING[3], paddingHorizontal: SPACING[4], backgroundColor: colors.bg.surface, borderRadius: RADIUS.LG, marginBottom: SPACING[2], gap: SPACING[3], }, workoutAvatar: { width: 44, height: 44, borderRadius: 22, alignItems: 'center', justifyContent: 'center', }, workoutInfo: { flex: 1, gap: 2, }, workoutMeta: { alignItems: 'flex-end', gap: 4, }, emptyState: { alignItems: 'center', justifyContent: 'center', paddingVertical: SPACING[12], }, }) }