// components/exercises/SimplifiedExerciseList.tsx import React, { useRef, useState, useCallback } from 'react'; import { View, SectionList, TouchableOpacity, ViewToken } from 'react-native'; import { Text } from '@/components/ui/text'; import { Badge } from '@/components/ui/badge'; import { ExerciseDisplay, WorkoutExercise } from '@/types/exercise'; // Create a combined interface for exercises that could have workout data interface DisplayWorkoutExercise extends ExerciseDisplay, WorkoutExercise {} interface SimplifiedExerciseListProps { exercises: ExerciseDisplay[]; onExercisePress: (exercise: ExerciseDisplay) => void; } export const SimplifiedExerciseList = ({ exercises, onExercisePress }: SimplifiedExerciseListProps) => { const sectionListRef = useRef(null); const [currentSection, setCurrentSection] = useState(''); // Organize exercises into sections const sections = React.useMemo(() => { const exercisesByLetter = exercises.reduce((acc, exercise) => { const firstLetter = exercise.title[0].toUpperCase(); if (!acc[firstLetter]) { acc[firstLetter] = []; } acc[firstLetter].push(exercise); return acc; }, {} as Record); return Object.entries(exercisesByLetter) .map(([letter, exercises]) => ({ title: letter, data: exercises.sort((a, b) => a.title.localeCompare(b.title)) })) .sort((a, b) => a.title.localeCompare(b.title)); }, [exercises]); const handleViewableItemsChanged = useCallback(({ viewableItems }: { viewableItems: ViewToken[]; }) => { const firstSection = viewableItems.find(item => item.section)?.section?.title; if (firstSection) { setCurrentSection(firstSection); } }, []); const scrollToSection = useCallback((letter: string) => { const sectionIndex = sections.findIndex(section => section.title === letter); if (sectionIndex !== -1 && sectionListRef.current) { sectionListRef.current.scrollToLocation({ animated: true, sectionIndex, itemIndex: 0, viewPosition: 0, }); } }, [sections]); const getItemLayout = useCallback((data: any, index: number) => ({ length: 85, // Approximate height of each item offset: 85 * index, index, }), []); const alphabet = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); const availableLetters = new Set(sections.map(section => section.title)); // Updated type guard function isWorkoutExercise(exercise: ExerciseDisplay): exercise is DisplayWorkoutExercise { return 'sets' in exercise && Array.isArray((exercise as any).sets); } const renderExerciseItem = ({ item }: { item: ExerciseDisplay }) => { const firstLetter = item.title.charAt(0).toUpperCase(); return ( onExercisePress(item)} className="flex-row items-center px-4 py-3 border-b border-border" > {/* Image placeholder or first letter */} {firstLetter} {/* Title */} {item.title} {/* Tags row */} {/* Category Badge */} {item.category} {/* Equipment Badge (if available) */} {item.equipment && ( {item.equipment} )} {/* Type Badge */} {item.type} {/* Source Badge - colored for 'powr' */} {item.source && ( {item.source} )} {/* Weight/Rep information if it was a WorkoutExercise */} {isWorkoutExercise(item) && ( {item.sets?.[0]?.weight && `${item.sets[0].weight} lb`} {item.sets?.[0]?.weight && item.sets?.[0]?.reps && ' '} {item.sets?.[0]?.reps && `(×${item.sets[0].reps})`} )} ); }; return ( {/* Main List */} item.id} getItemLayout={getItemLayout} renderSectionHeader={({ section }) => ( {section.title} )} renderItem={renderExerciseItem} stickySectionHeadersEnabled initialNumToRender={15} maxToRenderPerBatch={10} windowSize={5} onViewableItemsChanged={handleViewableItemsChanged} viewabilityConfig={{ itemVisiblePercentThreshold: 50 }} /> {/* Alphabet List */} true} onResponderMove={(evt) => { const touch = evt.nativeEvent; const element = evt.target; if (element) { (element as any).measure((x: number, y: number, width: number, height: number, pageX: number, pageY: number) => { const totalHeight = height; const letterHeight = totalHeight / alphabet.length; const touchY = touch.pageY - pageY; const index = Math.min( Math.max(Math.floor(touchY / letterHeight), 0), alphabet.length - 1 ); const letter = alphabet[index]; if (availableLetters.has(letter)) { scrollToSection(letter); } }); } }} > {alphabet.map((letter) => ( {letter} ))} ); }; export default SimplifiedExerciseList;