// 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.
)}
);
}