// app/(tabs)/profile/progress.tsx import React, { useState, useEffect } from 'react'; import { View, ScrollView, Switch, TouchableOpacity } from 'react-native'; import { Text } from '@/components/ui/text'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { useNDKCurrentUser } from '@/lib/hooks/useNDK'; import { ActivityIndicator } from 'react-native'; import { useAnalytics } from '@/lib/hooks/useAnalytics'; import { WorkoutStats, PersonalRecord, analyticsService } from '@/lib/services/AnalyticsService'; import { CloudIcon } from 'lucide-react-native'; // Period selector component function PeriodSelector({ period, setPeriod }: { period: 'week' | 'month' | 'year' | 'all', setPeriod: (period: 'week' | 'month' | 'year' | 'all') => void }) { return ( ); } // Format duration in hours and minutes function formatDuration(milliseconds: number): string { const hours = Math.floor(milliseconds / (1000 * 60 * 60)); const minutes = Math.floor((milliseconds % (1000 * 60 * 60)) / (1000 * 60)); return `${hours}h ${minutes}m`; } export default function ProgressScreen() { const { isAuthenticated } = useNDKCurrentUser(); const analytics = useAnalytics(); const [period, setPeriod] = useState<'week' | 'month' | 'year' | 'all'>('month'); const [loading, setLoading] = useState(true); const [stats, setStats] = useState(null); const [records, setRecords] = useState([]); const [includeNostr, setIncludeNostr] = useState(true); // Load workout statistics when period or includeNostr changes useEffect(() => { async function loadStats() { if (!isAuthenticated) return; try { setLoading(true); // Pass includeNostr flag to analytics service analyticsService.setIncludeNostr(includeNostr); const workoutStats = await analytics.getWorkoutStats(period); setStats(workoutStats); // Load personal records const personalRecords = await analytics.getPersonalRecords(undefined, 5); setRecords(personalRecords); } catch (error) { console.error('Error loading analytics data:', error); } finally { setLoading(false); } } loadStats(); }, [isAuthenticated, period, includeNostr, analytics]); // Workout frequency chart const WorkoutFrequencyChart = () => { const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; return ( Workout Frequency Chart {stats?.frequencyByDay.map((count, index) => ( {days[index]} ))} ); }; // Exercise distribution chart const ExerciseDistributionChart = () => { // Sample exercise names for demonstration const exerciseNames = [ 'Bench Press', 'Squat', 'Deadlift', 'Pull-up', 'Shoulder Press' ]; // Convert exercise distribution to percentages const exerciseDistribution = stats?.exerciseDistribution || {}; const total = Object.values(exerciseDistribution).reduce((sum, count) => sum + count, 0) || 1; const percentages = Object.entries(exerciseDistribution).reduce((acc, [id, count]) => { acc[id] = Math.round((count / total) * 100); return acc; }, {} as Record); // Take top 5 exercises const topExercises = Object.entries(percentages) .sort(([, a], [, b]) => b - a) .slice(0, 5); return ( Exercise Distribution {topExercises.map(([id, percentage], index) => ( {exerciseNames[index % exerciseNames.length].substring(0, 8)} ))} ); }; if (!isAuthenticated) { return ( Log in to view your progress ); } if (loading) { return ( ); } return ( {isAuthenticated && ( setIncludeNostr(!includeNostr)} className="flex-row items-center" > Nostr )} {/* Workout Summary */} Workout Summary Workouts: {stats?.workoutCount || 0} Total Time: {formatDuration(stats?.totalDuration || 0)} Total Volume: {(stats?.totalVolume || 0).toLocaleString()} lb {/* Workout Frequency Chart */} Workout Frequency {/* Muscle Group Distribution */} Exercise Distribution {/* Personal Records */} Personal Records {records.length === 0 ? ( No personal records yet. Complete more workouts to see your progress. ) : ( records.map((record) => ( {record.exerciseName} {record.value} {record.unit} × {record.reps} reps {new Date(record.date).toLocaleDateString()} {record.previousRecord && ( Previous: {record.previousRecord.value} {record.unit} )} )) )} {/* Nostr integration note */} {isAuthenticated && includeNostr && ( Analytics include workouts from Nostr. Toggle the switch above to view only local workouts. )} ); }