// app/(tabs)/library/exercises.tsx import React, { useState } from 'react'; import { View, ActivityIndicator, ScrollView } from 'react-native'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Search, Dumbbell, ListFilter } from 'lucide-react-native'; import { FloatingActionButton } from '@/components/shared/FloatingActionButton'; import { ExerciseSheet } from '@/components/library/ExerciseSheet'; import { SimplifiedExerciseList } from '@/components/exercises/SimplifiedExerciseList'; import { ModalExerciseDetails } from '@/components/exercises/ModalExerciseDetails'; import { ExerciseDisplay, ExerciseType, BaseExercise, Equipment } from '@/types/exercise'; import { useExercises } from '@/lib/hooks/useExercises'; import { FilterSheet, type FilterOptions, type SourceType } from '@/components/library/FilterSheet'; import { useWorkoutStore } from '@/stores/workoutStore'; import { generateId } from '@/utils/ids'; import { useNDKStore } from '@/lib/stores/ndk'; // Default available filters const availableFilters = { equipment: ['Barbell', 'Dumbbell', 'Bodyweight', 'Machine', 'Cables', 'Other'], tags: ['Strength', 'Cardio', 'Mobility', 'Recovery'], source: ['local', 'powr', 'nostr'] as SourceType[] }; // Initial filter state const initialFilters: FilterOptions = { equipment: [], tags: [], source: [] }; export default function ExercisesScreen() { // Basic state const [searchQuery, setSearchQuery] = useState(''); const [filterSheetOpen, setFilterSheetOpen] = useState(false); const [currentFilters, setCurrentFilters] = useState(initialFilters); const [activeFilters, setActiveFilters] = useState(0); // Exercise sheet state const [showExerciseSheet, setShowExerciseSheet] = useState(false); const [exerciseToEdit, setExerciseToEdit] = useState(undefined); const [editMode, setEditMode] = useState<'create' | 'edit' | 'fork'>('create'); // Exercise details state const [selectedExercise, setSelectedExercise] = useState(null); // Other hooks const { isActive, isMinimized } = useWorkoutStore(); const { currentUser } = useNDKStore(); const shouldShowFAB = !isActive || !isMinimized; const { exercises, loading, error, createExercise, deleteExercise, updateExercise, refreshExercises, updateFilters, clearFilters } = useExercises(); // Filter exercises based on search query React.useEffect(() => { if (searchQuery) { updateFilters({ searchQuery }); } else { updateFilters({ searchQuery: undefined }); } }, [searchQuery, updateFilters]); const handleExercisePress = (exercise: ExerciseDisplay) => { setSelectedExercise(exercise); }; // Mock exercise update function const handleUpdateExercise = async (id: string, updatedData: Partial): Promise => { try { // Since we don't have a real update function, we'll fake it with delete + create // In a real app, this would be replaced with an actual update API call console.log(`Updating exercise ${id} with data:`, updatedData); // Delete the old exercise await deleteExercise(id); // Create a new exercise with the same ID and updated data await createExercise({ ...updatedData, availability: updatedData.availability || { source: ['local'] } } as Omit); // Refresh the exercise list refreshExercises(); } catch (error) { console.error('Error updating exercise:', error); } }; // Handle editing an exercise const handleEdit = () => { if (!selectedExercise) return; // Close the details modal setSelectedExercise(null); // Determine if we should edit or fork based on Nostr ownership const isNostrExercise = selectedExercise.source === 'nostr'; const isCurrentUserAuthor = isNostrExercise && selectedExercise.availability?.lastSynced?.nostr?.metadata?.pubkey === currentUser?.pubkey; const mode = isNostrExercise && !isCurrentUserAuthor ? 'fork' : 'edit'; // Set up edit state setEditMode(mode); setExerciseToEdit(selectedExercise); // Open the exercise sheet setShowExerciseSheet(true); }; // Handle creating a new exercise const handleCreateExercise = () => { setEditMode('create'); setExerciseToEdit(undefined); setShowExerciseSheet(true); }; // Handle submitting exercise form (create, edit, or fork) const handleSubmitExercise = async (exerciseData: BaseExercise) => { try { if (editMode === 'create') { // For new exercises, ensure the availability is set const exerciseWithSource: Omit = { ...exerciseData, availability: { source: ['local'] } }; // Remove the ID from the data for new creation delete (exerciseWithSource as any).id; await createExercise(exerciseWithSource); } else if (editMode === 'edit') { // Use the new updateExercise function directly await updateExercise(exerciseData.id, exerciseData); } else if (editMode === 'fork') { // For forking, create a new exercise but keep the original data const { id: _, ...forkedExerciseData } = exerciseData; const forkedExercise: Omit = { ...forkedExerciseData, availability: { source: ['local'] // Start as a local exercise } }; await createExercise(forkedExercise); } // Refresh the exercise list after changes refreshExercises(); } catch (error) { console.error('Error handling exercise submission:', error); } // Close the sheet regardless of success/failure setShowExerciseSheet(false); }; const handleApplyFilters = (filters: FilterOptions) => { setCurrentFilters(filters); const totalFilters = Object.values(filters).reduce( (acc, curr) => acc + curr.length, 0 ); setActiveFilters(totalFilters); // Update the exercises hook filters with proper type casting if (filters.equipment.length > 0) { // Convert string[] to Equipment[] const typedEquipment = filters.equipment.filter(eq => ['bodyweight', 'barbell', 'dumbbell', 'kettlebell', 'machine', 'cable', 'other'].includes(eq.toLowerCase()) ) as Equipment[]; updateFilters({ equipment: typedEquipment }); } if (filters.tags.length > 0) { updateFilters({ tags: filters.tags }); } if (filters.source.length > 0) { updateFilters({ source: filters.source as any[] }); } if (totalFilters === 0) { clearFilters(); } }; return ( {/* Search bar with filter button */} {/* Filter Sheet */} setFilterSheetOpen(false)} options={currentFilters} onApplyFilters={handleApplyFilters} availableFilters={availableFilters} /> {/* Exercises list */} {/* Exercise details sheet */} setSelectedExercise(null)} onEdit={handleEdit} /> {/* FAB for adding new exercise */} {shouldShowFAB && ( )} {/* Exercise sheet for create/edit/fork */} setShowExerciseSheet(false)} onSubmit={handleSubmitExercise} exerciseToEdit={exerciseToEdit} mode={editMode} /> ); }