// app/(tabs)/history/workoutHistory.tsx import React, { useState, useEffect } from 'react'; import { View, ScrollView, ActivityIndicator, RefreshControl, Pressable } from 'react-native'; import { Text } from '@/components/ui/text'; import { Button } from '@/components/ui/button'; import { useSQLiteContext } from 'expo-sqlite'; import { Workout } from '@/types/workout'; import { format } from 'date-fns'; import { useNDKCurrentUser } from '@/lib/hooks/useNDK'; import WorkoutCard from '@/components/workout/WorkoutCard'; import NostrLoginSheet from '@/components/sheets/NostrLoginSheet'; import { useWorkoutHistory } from '@/lib/hooks/useWorkoutHistory'; // Define colors for icons and buttons const primaryColor = "#8b5cf6"; // Purple color const mutedColor = "#9ca3af"; // Gray color const primaryBgColor = "#8b5cf6"; // Purple background const primaryTextColor = "#ffffff"; // White text for purple background const mutedBgColor = "#f3f4f6"; // Light gray background const mutedTextColor = "#6b7280"; // Dark gray text for light background // Mock data for when database tables aren't yet created const mockWorkouts: Workout[] = [ { id: '1', title: 'Push 1', type: 'strength', exercises: [ { id: 'ex1', exerciseId: 'bench-press', title: 'Bench Press', type: 'strength', category: 'Push', sets: [], isCompleted: true, created_at: new Date('2025-03-07T10:00:00').getTime(), lastUpdated: new Date('2025-03-07T10:00:00').getTime(), availability: { source: ['local'] }, tags: ['compound', 'push'] }, { id: 'ex2', exerciseId: 'shoulder-press', title: 'Shoulder Press', type: 'strength', category: 'Push', sets: [], isCompleted: true, created_at: new Date('2025-03-07T10:00:00').getTime(), lastUpdated: new Date('2025-03-07T10:00:00').getTime(), availability: { source: ['local'] }, tags: ['compound', 'push'] }, { id: 'ex3', exerciseId: 'tricep-extension', title: 'Tricep Extension', type: 'strength', category: 'Push', sets: [], isCompleted: true, created_at: new Date('2025-03-07T10:00:00').getTime(), lastUpdated: new Date('2025-03-07T10:00:00').getTime(), availability: { source: ['local'] }, tags: ['isolation', 'push'] } ], startTime: new Date('2025-03-07T10:00:00').getTime(), endTime: new Date('2025-03-07T11:47:00').getTime(), isCompleted: true, created_at: new Date('2025-03-07T10:00:00').getTime(), availability: { source: ['local'] }, totalVolume: 9239 }, { id: '2', title: 'Pull 1', type: 'strength', exercises: [ { id: 'ex4', exerciseId: 'pull-up', title: 'Pull Up', type: 'strength', category: 'Pull', sets: [], isCompleted: true, created_at: new Date('2025-03-05T14:00:00').getTime(), lastUpdated: new Date('2025-03-05T14:00:00').getTime(), availability: { source: ['local'] }, tags: ['compound', 'pull'] }, { id: 'ex5', exerciseId: 'barbell-row', title: 'Barbell Row', type: 'strength', category: 'Pull', sets: [], isCompleted: true, created_at: new Date('2025-03-05T14:00:00').getTime(), lastUpdated: new Date('2025-03-05T14:00:00').getTime(), availability: { source: ['local'] }, tags: ['compound', 'pull'] } ], startTime: new Date('2025-03-05T14:00:00').getTime(), endTime: new Date('2025-03-05T15:36:00').getTime(), isCompleted: true, created_at: new Date('2025-03-05T14:00:00').getTime(), availability: { source: ['local'] }, totalVolume: 1396 } ]; // Group workouts by month const groupWorkoutsByMonth = (workouts: Workout[]) => { const grouped: Record = {}; workouts.forEach(workout => { const monthKey = format(workout.startTime, 'MMMM yyyy'); if (!grouped[monthKey]) { grouped[monthKey] = []; } grouped[monthKey].push(workout); }); return Object.entries(grouped); }; export default function HistoryScreen() { const db = useSQLiteContext(); const { isAuthenticated } = useNDKCurrentUser(); const [workouts, setWorkouts] = useState([]); const [isLoading, setIsLoading] = useState(true); const [useMockData, setUseMockData] = useState(false); const [refreshing, setRefreshing] = useState(false); const [includeNostr, setIncludeNostr] = useState(true); const [isLoginSheetOpen, setIsLoginSheetOpen] = useState(false); // Create memoized filters to prevent recreation on every render const filters = React.useMemo(() => { if (includeNostr) { return undefined; } else { // Explicitly type the array to match WorkoutFilters interface return { source: ['local' as const] }; } }, [includeNostr]); // Use the unified workout history hook const { workouts: allWorkouts, loading, refreshing: hookRefreshing, refresh, error } = useWorkoutHistory({ includeNostr, filters, realtime: true }); // Set workouts from the hook with more careful state updates useEffect(() => { if (loading) { setIsLoading(true); return; // Exit early to avoid multiple state updates in one effect } setIsLoading(false); setRefreshing(false); // Check if we need to use mock data (empty workouts) if (allWorkouts.length === 0 && !error) { console.log('No workouts found, using mock data'); setWorkouts(mockWorkouts); setUseMockData(true); } else { setWorkouts(allWorkouts); setUseMockData(false); } }, [allWorkouts, loading, error, mockWorkouts]); // Pull to refresh handler const onRefresh = React.useCallback(() => { setRefreshing(true); refresh(); }, [refresh]); // Group workouts by month const groupedWorkouts = groupWorkoutsByMonth(workouts); return ( } > {/* Nostr Login Prompt */} {!isAuthenticated && ( Connect with Nostr Login with Nostr to see your workouts from other devices and back up your workout history. )} {isLoading && !refreshing ? ( Loading workout history... ) : workouts.length === 0 ? ( No workouts recorded yet. Complete a workout to see it here. ) : ( // Display grouped workouts by month {useMockData && ( Showing example data. Your completed workouts will appear here. )} {isAuthenticated && ( Workout Source setIncludeNostr(true)} style={{ backgroundColor: includeNostr ? primaryBgColor : 'transparent', paddingHorizontal: 12, paddingVertical: 6, }} > All Workouts setIncludeNostr(false)} style={{ backgroundColor: !includeNostr ? primaryBgColor : 'transparent', paddingHorizontal: 12, paddingVertical: 6, }} > Local Only {includeNostr ? 'Showing all workouts from Nostr and your local device' : 'Only showing workouts saved on this device'} )} {groupedWorkouts.map(([month, monthWorkouts]) => ( {month.toUpperCase()} {monthWorkouts.map((workout) => ( ))} ))} )} {/* Add bottom padding for better scrolling experience */} {/* Nostr Login Sheet */} setIsLoginSheetOpen(false)} /> ); }