diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f79218..9e49b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Optimized rendering for long lists with virtualized FlatList - Added scrollToTop functionality for new content +## Fixed +- Template creation issue: preserved original exercise IDs when creating templates to ensure proper exercise references + - Modified NewTemplateSheet to store full exercise objects + - Updated handleAddTemplate to use original exercise IDs + - Fixed type definitions to support enhanced template exercises + # Changelog - March 19, 2025 ## Added @@ -456,4 +462,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial repository setup - Basic project structure - Development environment configuration -- Documentation templates \ No newline at end of file +- Documentation templates diff --git a/app/(tabs)/library/templates.tsx b/app/(tabs)/library/templates.tsx index 5ae0572..64775c9 100644 --- a/app/(tabs)/library/templates.tsx +++ b/app/(tabs)/library/templates.tsx @@ -15,8 +15,22 @@ import { Button } from '@/components/ui/button'; import { Template, TemplateCategory, + TemplateExerciseConfig, + TemplateExerciseDisplay, toWorkoutTemplate } from '@/types/templates'; +import { generateId } from '@/utils/ids'; +import { ExerciseDisplay } from '@/types/exercise'; + +// Enhanced template exercise display that includes the original exercise object +interface EnhancedTemplateExerciseDisplay { + title: string; + targetSets: number; + targetReps: number; + equipment?: string; + notes?: string; + exercise: ExerciseDisplay; +} import { useWorkoutStore } from '@/stores/workoutStore'; import { useTemplates } from '@/lib/hooks/useTemplates'; import { useIconColor } from '@/lib/theme/iconUtils'; @@ -165,8 +179,28 @@ export default function TemplatesScreen() { }; const handleAddTemplate = (template: Template) => { - // Convert UI Template to WorkoutTemplate - const workoutTemplate = toWorkoutTemplate(template); + // The template exercises should already have the exercise property from NewTemplateSheet + // We know the exercises have the exercise property because we modified NewTemplateSheet + const enhancedExercises = template.exercises as unknown as EnhancedTemplateExerciseDisplay[]; + + // Convert UI Template to WorkoutTemplate, but preserve exercise IDs + const baseWorkoutTemplate = toWorkoutTemplate(template); + + // Modify the exercises to use the original exercise objects with their IDs + const workoutTemplate = { + ...baseWorkoutTemplate, + exercises: enhancedExercises.map(ex => { + // Create a proper TemplateExerciseConfig object + const config: TemplateExerciseConfig = { + id: generateId(), // ID for the template_exercise relationship + exercise: ex.exercise, // Use the original exercise object with its ID + targetSets: ex.targetSets, + targetReps: ex.targetReps, + notes: ex.notes + }; + return config; + }) + }; // Create the template createTemplate(workoutTemplate); @@ -332,4 +366,4 @@ export default function TemplatesScreen() { /> ); -} \ No newline at end of file +} diff --git a/components/library/NewTemplateSheet.tsx b/components/library/NewTemplateSheet.tsx index 8e739c3..33e0d23 100644 --- a/components/library/NewTemplateSheet.tsx +++ b/components/library/NewTemplateSheet.tsx @@ -31,6 +31,11 @@ type CreationStep = 'type' | 'info' | 'exercises' | 'config' | 'review'; // Purple color used throughout the app const purpleColor = 'hsl(261, 90%, 66%)'; +// Enhanced template exercise display that includes the original exercise object +interface EnhancedTemplateExerciseDisplay extends TemplateExerciseDisplay { + exercise: ExerciseDisplay; +} + // Step 0: Workout Type Selection interface WorkoutTypeStepProps { onSelectType: (type: TemplateType) => void; @@ -234,6 +239,7 @@ function ExerciseSelectionStep({ }; const handleContinue = () => { + // Get the full exercise objects with their original IDs const selected = exercises.filter(e => selectedIds.includes(e.id)); onExercisesSelected(selected); }; @@ -322,7 +328,7 @@ function ExerciseSelectionStep({ // Step 3: Exercise Configuration interface ExerciseConfigStepProps { exercises: ExerciseDisplay[]; - config: TemplateExerciseDisplay[]; + config: EnhancedTemplateExerciseDisplay[]; onUpdateConfig: (index: number, sets: number, reps: number) => void; onNext: () => void; onBack: () => void; @@ -397,7 +403,7 @@ interface ReviewStepProps { description: string; category: TemplateCategory; type: TemplateType; - exercises: Template['exercises']; + exercises: EnhancedTemplateExerciseDisplay[]; onSubmit: () => void; onBack: () => void; } @@ -469,7 +475,7 @@ export function NewTemplateSheet({ isOpen, onClose, onSubmit }: NewTemplateSheet const [workoutType, setWorkoutType] = useState('strength'); const [exercises, setExercises] = useState([]); const [selectedExercises, setSelectedExercises] = useState([]); - const [configuredExercises, setConfiguredExercises] = useState([]); + const [configuredExercises, setConfiguredExercises] = useState([]); const { isDarkColorScheme } = useColorScheme(); // Template info @@ -544,9 +550,10 @@ export function NewTemplateSheet({ isOpen, onClose, onSubmit }: NewTemplateSheet const handleSelectExercises = (selected: ExerciseDisplay[]) => { setSelectedExercises(selected); - // Pre-populate configured exercises + // Pre-populate configured exercises with full exercise objects const initialConfig = selected.map(exercise => ({ title: exercise.title, + exercise: exercise, // Store the complete exercise object with its original ID targetSets: 0, targetReps: 0 })); @@ -706,4 +713,4 @@ export function NewTemplateSheet({ isOpen, onClose, onSubmit }: NewTemplateSheet ); -} \ No newline at end of file +}