import { useState, useEffect } from 'react'; import { WorkoutSession, WorkoutSet, ExerciseDef, WorkoutPlan } from '../../types'; import { getExercises, saveExercise, getPlans } from '../../services/storage'; import { api } from '../../services/api'; import { useSessionTimer } from '../../hooks/useSessionTimer'; import { useWorkoutForm } from '../../hooks/useWorkoutForm'; import { usePlanExecution } from '../../hooks/usePlanExecution'; import { useAuth } from '../../context/AuthContext'; import { useActiveWorkout } from '../../context/ActiveWorkoutContext'; import { useSession } from '../../context/SessionContext'; import { useRestTimer } from '../../hooks/useRestTimer'; export const useTracker = (props: any) => { // Props ignored/removed const { currentUser } = useAuth(); const userId = currentUser?.id || ''; const userWeight = currentUser?.profile?.weight; const { activeSession, activePlan, startSession, addSet, updateSet, quitSession, endSession, removeSet } = useActiveWorkout(); const { refreshData: refreshHistory } = useSession(); const [exercises, setExercises] = useState([]); const [plans, setPlans] = useState([]); const [selectedExercise, setSelectedExercise] = useState(null); const [lastSet, setLastSet] = useState(undefined); const [searchQuery, setSearchQuery] = useState(''); const [showSuggestions, setShowSuggestions] = useState(false); // User Weight State const [userBodyWeight, setUserBodyWeight] = useState(userWeight ? userWeight.toString() : '70'); // Create Exercise State const [isCreating, setIsCreating] = useState(false); // Confirmation State const [showFinishConfirm, setShowFinishConfirm] = useState(false); const [showQuitConfirm, setShowQuitConfirm] = useState(false); const [showMenu, setShowMenu] = useState(false); // Quick Log State const [quickLogSession, setQuickLogSession] = useState(null); const [isSporadicMode, setIsSporadicMode] = useState(false); const [sporadicSuccess, setSporadicSuccess] = useState(false); // Last Workout State const [lastWorkoutDate, setLastWorkoutDate] = useState(null); // Hooks const elapsedTime = useSessionTimer(activeSession); // useWorkoutForm needs onUpdateSet. But context updateSet signature might be different? // context: updateSet(setId, updates). useWorkoutForm expects onUpdateSet(set). // We can adaptor. const handleUpdateSetWrapper = (set: WorkoutSet) => { updateSet(set.id, set); }; const form = useWorkoutForm({ userId, onUpdateSet: handleUpdateSetWrapper }); const planExec = usePlanExecution({ activeSession, activePlan, exercises }); // Rest Timer Logic (Moved from ActiveSessionView to persist state) const getTargetRestTime = () => { if (activePlan) { const currentStep = activePlan.steps[planExec.currentStepIndex]; if (currentStep && currentStep.restTimeSeconds) { return currentStep.restTimeSeconds; } } return currentUser?.profile?.restTimerDefault || 120; }; const targetRestTime = getTargetRestTime(); const timer = useRestTimer({ defaultTime: targetRestTime }); // Initial Data Load useEffect(() => { if (!userId) return; const loadData = async () => { const exList = await getExercises(userId); exList.sort((a, b) => a.name.localeCompare(b.name)); setExercises(exList); const planList = await getPlans(userId); setPlans(planList); if (activeSession?.userBodyWeight) { setUserBodyWeight(activeSession.userBodyWeight.toString()); } else if (userWeight) { setUserBodyWeight(userWeight.toString()); } try { const lastSessionRes = await api.get('/sessions/active/last'); if (lastSessionRes.success && lastSessionRes.data?.session?.endTime) { setLastWorkoutDate(new Date(lastSessionRes.data.session.endTime)); } else { setLastWorkoutDate(null); } } catch (err) { console.error("Failed to load last session", err); } loadQuickLogSession(); }; loadData(); }, [activeSession?.id, userId, userWeight, activePlan?.id, isSporadicMode]); // Function to reload Quick Log session const loadQuickLogSession = async () => { try { const response = await api.get('/sessions/quick-log'); if (response.success && response.data?.session) { setQuickLogSession(response.data.session); } } catch (error) { console.error("Failed to load quick log session:", error); } }; // Auto-select exercise from plan step useEffect(() => { const step = planExec.getCurrentStep(); if (step) { const exDef = exercises.find(e => e.id === step.exerciseId); if (exDef && selectedExercise?.id !== exDef.id) { setSelectedExercise(exDef); } } }, [planExec.currentStepIndex, activePlan, exercises]); // Update form when exercise changes useEffect(() => { const updateSelection = async () => { if (selectedExercise) { setSearchQuery(selectedExercise.name); // Reset form synchronously to clear previous exercise data immediately form.resetForm(); await form.updateFormFromLastSet(selectedExercise.id, selectedExercise.type, selectedExercise.bodyWeightPercentage); } else { setSearchQuery(''); form.resetForm(); } }; updateSelection(); }, [selectedExercise, userId]); const filteredExercises = searchQuery === '' ? exercises : exercises.filter(ex => ex.name.toLowerCase().includes(searchQuery.toLowerCase()) ); const handleStart = (plan?: WorkoutPlan) => { if (plan && plan.description) { planExec.setShowPlanPrep(plan); } else { startSession(plan, parseFloat(userBodyWeight)); } }; const confirmPlanStart = () => { if (planExec.showPlanPrep) { startSession(planExec.showPlanPrep, parseFloat(userBodyWeight)); planExec.setShowPlanPrep(null); } } const handleAddSet = async () => { if (!activeSession || !selectedExercise) return; const setData = form.prepareSetData(selectedExercise); await addSet(setData); }; const handleLogSporadicSet = async () => { if (!selectedExercise) return; const setData = form.prepareSetData(selectedExercise); try { const response = await api.post('/sessions/quick-log/set', setData); if (response.success) { setSporadicSuccess(true); setTimeout(() => setSporadicSuccess(false), 2000); loadQuickLogSession(); // form.resetForm(); // Persist values refreshHistory(); } } catch (error) { console.error("Failed to log quick log set:", error); } }; const handleCreateExercise = async (newEx: ExerciseDef) => { await saveExercise(userId, newEx); setExercises(prev => [...prev, newEx].sort((a, b) => a.name.localeCompare(b.name))); setSelectedExercise(newEx); setSearchQuery(newEx.name); setIsCreating(false); }; // Forwarding form handlers from hook const handleEditSet = form.startEditing; const handleSaveEdit = form.saveEdit; const handleCancelEdit = form.cancelEdit; // Reset override const resetForm = () => { form.resetForm(); setSelectedExercise(null); setSearchQuery(''); setSporadicSuccess(false); }; return { exercises, plans, activePlan, selectedExercise, setSelectedExercise, lastSet, searchQuery, setSearchQuery, showSuggestions, setShowSuggestions, elapsedTime, // Form Props weight: form.weight, setWeight: form.setWeight, reps: form.reps, setReps: form.setReps, duration: form.duration, setDuration: form.setDuration, distance: form.distance, setDistance: form.setDistance, height: form.height, setHeight: form.setHeight, bwPercentage: form.bwPercentage, setBwPercentage: form.setBwPercentage, unilateralSide: form.unilateralSide, setUnilateralSide: form.setUnilateralSide, userBodyWeight, setUserBodyWeight, isCreating, setIsCreating, // Plan Execution Props currentStepIndex: planExec.currentStepIndex, showPlanPrep: planExec.showPlanPrep, setShowPlanPrep: planExec.setShowPlanPrep, showPlanList: planExec.showPlanList, setShowPlanList: planExec.setShowPlanList, jumpToStep: planExec.jumpToStep, showFinishConfirm, setShowFinishConfirm, showQuitConfirm, setShowQuitConfirm, showMenu, setShowMenu, // Editing editingSetId: form.editingSetId, editWeight: form.editWeight, setEditWeight: form.setEditWeight, editReps: form.editReps, setEditReps: form.setEditReps, editDuration: form.editDuration, setEditDuration: form.setEditDuration, editDistance: form.editDistance, setEditDistance: form.setEditDistance, editHeight: form.editHeight, setEditHeight: form.setEditHeight, editSide: form.editSide, setEditSide: form.setEditSide, isSporadicMode, setIsSporadicMode, sporadicSuccess, filteredExercises, handleStart, confirmPlanStart, handleAddSet, handleLogSporadicSet, handleCreateExercise, handleEditSet, handleSaveEdit, handleCancelEdit, resetForm, quickLogSession, loadQuickLogSession, // Pass through context methods for UI to use onSessionEnd: endSession, onSessionQuit: quitSession, onRemoveSet: removeSet, updateSet: handleUpdateSetWrapper, activeSession, // Need this in view timer, // Expose timer to views lastWorkoutDate }; };