2025-02-19 21:39:47 -05:00
|
|
|
// types/exercise.ts
|
|
|
|
import { SyncableContent } from './shared';
|
2025-02-09 20:38:38 -05:00
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Core Exercise Classifications
|
|
|
|
* These types define the fundamental ways we categorize exercises
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export type ExerciseType = 'strength' | 'cardio' | 'bodyweight';
|
2025-02-19 21:39:47 -05:00
|
|
|
|
2025-02-09 20:38:38 -05:00
|
|
|
export type ExerciseCategory = 'Push' | 'Pull' | 'Legs' | 'Core';
|
2025-02-19 21:39:47 -05:00
|
|
|
|
2025-02-09 20:38:38 -05:00
|
|
|
export type Equipment =
|
|
|
|
| 'bodyweight'
|
|
|
|
| 'barbell'
|
|
|
|
| 'dumbbell'
|
|
|
|
| 'kettlebell'
|
|
|
|
| 'machine'
|
|
|
|
| 'cable'
|
|
|
|
| 'other';
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Exercise Format Configuration
|
|
|
|
* Defines how an exercise should be tracked and measured
|
|
|
|
*/
|
|
|
|
export interface ExerciseFormat {
|
|
|
|
weight?: boolean;
|
|
|
|
reps?: boolean;
|
|
|
|
rpe?: boolean;
|
|
|
|
set_type?: boolean;
|
|
|
|
}
|
2025-02-16 23:53:28 -05:00
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
export interface ExerciseFormatUnits {
|
|
|
|
weight?: 'kg' | 'lbs';
|
|
|
|
reps?: 'count';
|
|
|
|
rpe?: '0-10';
|
|
|
|
set_type?: 'warmup|normal|drop|failure';
|
2025-02-09 20:38:38 -05:00
|
|
|
}
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Base Exercise Definition
|
|
|
|
* Contains the core properties that define an exercise
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export interface BaseExercise extends SyncableContent {
|
|
|
|
title: string;
|
|
|
|
type: ExerciseType;
|
|
|
|
category: ExerciseCategory;
|
|
|
|
equipment?: Equipment;
|
|
|
|
description?: string;
|
|
|
|
instructions?: string[];
|
|
|
|
tags: string[];
|
2025-02-19 21:39:47 -05:00
|
|
|
format?: ExerciseFormat;
|
|
|
|
format_units?: ExerciseFormatUnits;
|
2025-02-09 20:38:38 -05:00
|
|
|
}
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Exercise UI Display
|
|
|
|
* Extends BaseExercise with UI-specific properties
|
|
|
|
*/
|
|
|
|
export interface ExerciseDisplay extends BaseExercise {
|
|
|
|
source: 'local' | 'powr' | 'nostr';
|
|
|
|
usageCount?: number;
|
|
|
|
lastUsed?: Date;
|
|
|
|
isFavorite?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set Types and Tracking
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export type SetType = 'warmup' | 'normal' | 'drop' | 'failure';
|
|
|
|
|
|
|
|
export interface WorkoutSet {
|
|
|
|
id: string;
|
|
|
|
weight?: number;
|
|
|
|
reps?: number;
|
|
|
|
rpe?: number;
|
|
|
|
type: SetType;
|
|
|
|
isCompleted: boolean;
|
|
|
|
notes?: string;
|
|
|
|
timestamp?: number;
|
2025-03-08 15:48:07 -05:00
|
|
|
duration?: number; // Add this property
|
|
|
|
completedAt?: number;
|
|
|
|
lastUpdated?: number;
|
2025-02-09 20:38:38 -05:00
|
|
|
}
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Exercise with active workout data
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export interface WorkoutExercise extends BaseExercise {
|
|
|
|
sets: WorkoutSet[];
|
2025-03-08 15:48:07 -05:00
|
|
|
exerciseId?: string;
|
2025-02-09 20:38:38 -05:00
|
|
|
targetSets?: number;
|
|
|
|
targetReps?: number;
|
2025-02-24 22:27:01 -05:00
|
|
|
notes?: string;
|
|
|
|
restTime?: number;
|
|
|
|
isCompleted?: boolean;
|
|
|
|
lastUpdated?: number;
|
2025-02-09 20:38:38 -05:00
|
|
|
}
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Exercise Template with recommendations and progression
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export interface ExerciseTemplate extends BaseExercise {
|
|
|
|
defaultSets?: {
|
|
|
|
type: SetType;
|
|
|
|
weight?: number;
|
|
|
|
reps?: number;
|
|
|
|
rpe?: number;
|
|
|
|
}[];
|
|
|
|
recommendations?: {
|
|
|
|
beginnerWeight?: number;
|
|
|
|
intermediateWeight?: number;
|
|
|
|
advancedWeight?: number;
|
|
|
|
restTime?: number;
|
|
|
|
tempo?: string;
|
|
|
|
};
|
|
|
|
variations?: string[];
|
|
|
|
progression?: {
|
|
|
|
type: 'linear' | 'percentage' | 'custom';
|
|
|
|
increment?: number;
|
|
|
|
rules?: string[];
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2025-02-19 21:39:47 -05:00
|
|
|
/**
|
|
|
|
* Exercise History Tracking
|
|
|
|
*/
|
2025-02-09 20:38:38 -05:00
|
|
|
export interface ExerciseHistory {
|
|
|
|
exerciseId: string;
|
|
|
|
entries: Array<{
|
|
|
|
date: number;
|
|
|
|
workoutId: string;
|
|
|
|
sets: WorkoutSet[];
|
|
|
|
totalWeight: number;
|
|
|
|
notes?: string;
|
|
|
|
}>;
|
|
|
|
personalBests: {
|
|
|
|
weight?: {
|
|
|
|
value: number;
|
|
|
|
date: number;
|
|
|
|
workoutId: string;
|
|
|
|
};
|
|
|
|
reps?: {
|
|
|
|
value: number;
|
|
|
|
date: number;
|
|
|
|
workoutId: string;
|
|
|
|
};
|
|
|
|
volume?: {
|
|
|
|
value: number;
|
|
|
|
date: number;
|
|
|
|
workoutId: string;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Type guards
|
|
|
|
export function isWorkoutExercise(exercise: any): exercise is WorkoutExercise {
|
|
|
|
return exercise && Array.isArray(exercise.sets);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isExerciseTemplate(exercise: any): exercise is ExerciseTemplate {
|
|
|
|
return exercise && 'recommendations' in exercise;
|
2025-02-19 21:39:47 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a BaseExercise to ExerciseDisplay
|
|
|
|
*/
|
|
|
|
export function toExerciseDisplay(exercise: BaseExercise): ExerciseDisplay {
|
|
|
|
return {
|
|
|
|
...exercise, // Include all BaseExercise properties
|
|
|
|
source: exercise.availability.source.includes('nostr')
|
|
|
|
? 'nostr'
|
|
|
|
: exercise.availability.source.includes('powr')
|
|
|
|
? 'powr'
|
|
|
|
: 'local',
|
|
|
|
isFavorite: false
|
|
|
|
};
|
2025-02-09 20:38:38 -05:00
|
|
|
}
|