// components/workout/WorkoutDetailView.tsx import React from 'react'; import { View, ScrollView, TouchableOpacity } from 'react-native'; import { Text } from '@/components/ui/text'; import { format } from 'date-fns'; import { Card, CardContent } from '@/components/ui/card'; import { Workout, WorkoutExercise, WorkoutSet } from '@/types/workout'; import { CloudIcon, SmartphoneIcon, CloudOffIcon, Share2Icon, DownloadIcon } from 'lucide-react-native'; import { formatDuration } from '@/utils/formatTime'; interface WorkoutDetailViewProps { workout: Workout; onPublish?: () => void; onImport?: () => void; onExport?: (format: 'csv' | 'json') => void; } export const WorkoutDetailView: React.FC = ({ workout, onPublish, onImport, onExport }) => { // Determine source const workoutSource = (workout.availability?.source?.includes('nostr') && workout.availability?.source?.includes('local') ? 'both' : workout.availability?.source?.includes('nostr') ? 'nostr' : 'local'); // Determine publish status const isPublished = Boolean(workout.availability?.nostrEventId); const relayCount = workout.availability?.nostrRelayCount || 0; const lastPublished = workout.availability?.nostrPublishedAt; // Format workout duration const duration = workout.endTime && workout.startTime ? formatDuration(workout.endTime - workout.startTime) : 'N/A'; // Render a set const renderSet = (set: WorkoutSet, index: number) => ( {index + 1} {set.weight && ( {set.weight} lb )} {set.reps && ( {set.reps} reps )} {set.rpe && ( RPE {set.rpe} )} {set.isCompleted ? 'Completed' : 'Skipped'} ); // Render an exercise with its sets const renderExercise = (exercise: WorkoutExercise, index: number) => ( {index + 1}. {exercise.title} {exercise.sets.length} sets {exercise.notes && ( {exercise.notes} )} {/* Set header */} Set Weight/Reps Status {/* Sets */} {exercise.sets.map((set, idx) => renderSet(set, idx))} ); return ( {/* Header */} {workout.title} {/* Source indicator */} {workoutSource === 'local' && ( <> Local )} {workoutSource === 'nostr' && ( <> Nostr )} {workoutSource === 'both' && ( <> Both )} {format(workout.startTime, 'EEEE, MMMM d, yyyy')} at {format(workout.startTime, 'h:mm a')} {/* Publish status */} {workoutSource !== 'nostr' && ( {isPublished ? ( Published to {relayCount} relays {lastPublished && ` on ${format(lastPublished, 'MMM d, yyyy')}`} ) : ( Local only )} )} {/* Action buttons */} {/* Publish button for local workouts */} {workoutSource !== 'nostr' && !isPublished && onPublish && ( Publish to Nostr )} {/* Republish button for already published workouts */} {workoutSource !== 'nostr' && isPublished && onPublish && ( Republish )} {/* Import button for Nostr-only workouts */} {workoutSource === 'nostr' && onImport && ( Import to local )} {/* Export buttons */} {onExport && ( onExport('json')} className="mr-2 mb-2 flex-row items-center bg-muted px-3 py-2 rounded" > Export JSON onExport('csv')} className="mr-2 mb-2 flex-row items-center bg-muted px-3 py-2 rounded" > Export CSV )} {/* Workout stats */} Duration {duration} Total Volume {workout.totalVolume ? `${workout.totalVolume} lb` : 'N/A'} Total Reps {workout.totalReps || 'N/A'} Exercises {workout.exercises?.length || 0} {/* Notes */} {workout.notes && ( Notes {workout.notes} )} {/* Exercises */} Exercises {workout.exercises && workout.exercises.length > 0 ? ( workout.exercises.map((exercise, idx) => renderExercise(exercise, idx)) ) : ( No exercises recorded )} {/* Add bottom padding for better scrolling experience */} ); }; export default WorkoutDetailView;