// app/(workout)/create.tsx import React, { useState, useEffect } from 'react'; import { View, ScrollView, StyleSheet, TouchableOpacity } from 'react-native'; import { router, useNavigation } from 'expo-router'; import { TabScreen } from '@/components/layout/TabScreen'; import { Text } from '@/components/ui/text'; import { Button } from '@/components/ui/button'; import { AlertDialog, AlertDialogAction, AlertDialogContent, AlertDialogDescription, AlertDialogHeader, AlertDialogTitle, AlertDialogCancel } from '@/components/ui/alert-dialog'; import { useWorkoutStore } from '@/stores/workoutStore'; import { Plus, Pause, Play, MoreHorizontal, Dumbbell, ChevronLeft } from 'lucide-react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import EditableText from '@/components/EditableText'; import { cn } from '@/lib/utils'; import { generateId } from '@/utils/ids'; import { WorkoutSet } from '@/types/workout'; import { formatTime } from '@/utils/formatTime'; import { ParamListBase } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import SetInput from '@/components/workout/SetInput'; import { useColorScheme } from '@/lib/theme/useColorScheme'; import { WorkoutAlertDialog } from '@/components/workout/WorkoutAlertDialog'; import { useIconColor } from '@/lib/theme/iconUtils'; export default function CreateWorkoutScreen() { const { status, activeWorkout, elapsedTime, restTimer, clearAutoSave, isMinimized } = useWorkoutStore(); const { pauseWorkout, resumeWorkout, completeWorkout, updateWorkoutTitle, updateSet, cancelWorkout, minimizeWorkout, maximizeWorkout } = useWorkoutStore.getState(); // Get theme colors const { isDarkColorScheme } = useColorScheme(); // Get icon utilities const { getIconProps } = useIconColor(); // Create dynamic styles based on theme const dynamicStyles = StyleSheet.create({ timerText: { fontVariant: ['tabular-nums'] }, cardContainer: { marginBottom: 24, backgroundColor: isDarkColorScheme ? '#1F1F23' : 'white', borderRadius: 8, borderWidth: 1, borderColor: isDarkColorScheme ? '#333' : '#eee', shadowColor: '#000', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.2, shadowRadius: 2, elevation: 2, }, cardHeader: { padding: 16, flexDirection: 'row', justifyContent: 'space-between', borderBottomWidth: 1, borderBottomColor: isDarkColorScheme ? '#333' : '#eee' }, cardTitle: { fontSize: 18, fontWeight: 'bold', color: '#8B5CF6' // Purple is used in both themes }, setsInfo: { paddingHorizontal: 16, paddingVertical: 4 }, setsInfoText: { fontSize: 14, color: isDarkColorScheme ? '#999' : '#666' }, headerRow: { flexDirection: 'row', paddingHorizontal: 16, paddingVertical: 4, borderTopWidth: 1, borderTopColor: isDarkColorScheme ? '#333' : '#eee', backgroundColor: isDarkColorScheme ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.03)' }, headerCell: { fontSize: 14, fontWeight: '500', color: isDarkColorScheme ? '#999' : '#666', textAlign: 'center' }, setNumberCell: { width: 32 }, prevCell: { width: 80 }, valueCell: { flex: 1 }, spacer: { width: 44 }, setsList: { padding: 0 }, actionButton: { borderTopWidth: 1, borderTopColor: isDarkColorScheme ? '#333' : '#eee' }, iconColor: { color: isDarkColorScheme ? '#999' : '#666' } }); type CreateScreenNavigationProp = NativeStackNavigationProp; const navigation = useNavigation(); // Check if we're coming from minimized state when component mounts useEffect(() => { if (isMinimized) { maximizeWorkout(); } }, [isMinimized, maximizeWorkout]); // Handle back navigation useEffect(() => { const unsubscribe = navigation.addListener('beforeRemove', (e) => { // If we have an active workout, just minimize it before continuing if (activeWorkout && !isMinimized) { // Call minimizeWorkout to update the state minimizeWorkout(); // Let the navigation continue naturally // Don't call router.back() here to avoid recursion } }); return unsubscribe; }, [navigation, activeWorkout, isMinimized, minimizeWorkout]); const [showFinishDialog, setShowFinishDialog] = useState(false); const [showCancelDialog, setShowCancelDialog] = useState(false); const insets = useSafeAreaInsets(); // Handler for confirming workout cancellation const confirmCancelWorkout = async () => { setShowCancelDialog(false); // If cancelWorkout exists in the store, use it if (typeof cancelWorkout === 'function') { await cancelWorkout(); } else { // Otherwise use the clearAutoSave function await clearAutoSave(); } router.back(); }; // Handler for adding a new set to an exercise const handleAddSet = (exerciseIndex: number) => { if (!activeWorkout) return; const exercise = activeWorkout.exercises[exerciseIndex]; const lastSet = exercise.sets[exercise.sets.length - 1]; const newSet: WorkoutSet = { id: generateId('local'), weight: lastSet?.weight || 0, reps: lastSet?.reps || 0, type: 'normal', isCompleted: false }; updateSet(exerciseIndex, exercise.sets.length, newSet); }; // Show empty state when no workout is active if (!activeWorkout) { return ( No active workout ); } // Show rest timer overlay when active if (restTimer.isActive) { return ( {/* Timer Display */} Rest Timer {formatTime(restTimer.remaining * 1000)} {/* Controls */} ); } const hasExercises = activeWorkout.exercises.length > 0; return ( {/* Header with back button */} Back {/* Full-width workout title */} updateWorkoutTitle(newTitle)} placeholder="Workout Title" textStyle={{ fontSize: 24, fontWeight: '700', }} /> {/* Timer Display */} {formatTime(elapsedTime)} {status === 'active' ? ( ) : ( )} {/* Content Area */} {hasExercises ? ( // Exercise List when exercises exist <> {activeWorkout.exercises.map((exercise, exerciseIndex) => ( {/* Exercise Header */} {exercise.title} console.log('Open exercise options')}> {/* Sets Info */} {exercise.sets.filter(s => s.isCompleted).length} sets completed {/* Set Headers */} SET PREV KG REPS {/* Exercise Sets */} {exercise.sets.map((set, setIndex) => { const previousSet = setIndex > 0 ? exercise.sets[setIndex - 1] : undefined; return ( ); })} {/* Add Set Button */} ))} {/* Add Exercises Button */} {/* Cancel Button */} ) : ( // Empty State with nice message and icon No exercises added Add exercises to start tracking your workout {/* Add Exercises Button for empty state */} {/* Cancel Button for empty state */} )} {/* Finish Workout Dialog */} { setShowFinishDialog(false); // Set the end time before navigating useWorkoutStore.setState(state => ({ activeWorkout: state.activeWorkout ? { ...state.activeWorkout, endTime: Date.now(), lastUpdated: Date.now() } : null })); // Navigate to completion screen router.push('/(workout)/complete'); }} title="Complete Workout?" description="Are you sure you want to finish this workout? This will end your current session." confirmText="Complete Workout" /> {/* Cancel Workout Dialog */} Cancel Workout Are you sure you want to cancel this workout? All progress will be lost. setShowCancelDialog(false)}> Continue Workout Cancel Workout ); }