fitness: add per-exercise metrics, cardio support, and stats page
All checks were successful
CI / update (push) Successful in 2m0s

- Add metrics system (weight/reps/rpe/distance/duration) per exercise type
  so cardio exercises show distance+duration instead of weight+reps
- Add 8 new cardio exercises: swimming, hiking, rowing outdoor, cycling
  outdoor, elliptical, stair climber, jump rope, walking
- Add bilateral flag to dumbbell exercises for accurate tonnage calculation
- Make SetTable, SessionCard, history detail, template editor, and exercise
  stats API all render/compute dynamically based on exercise metrics
- Rename Profile to Stats with lifetime cards: workouts, tonnage, cardio km
- Move route /fitness/profile -> /fitness/stats, API /stats/profile -> /stats/overview
This commit is contained in:
2026-03-19 18:57:49 +01:00
parent 14da4064a5
commit 828d4a83b0
16 changed files with 588 additions and 272 deletions

View File

@@ -1,9 +1,11 @@
import mongoose from 'mongoose';
export interface ICompletedSet {
reps: number;
reps?: number;
weight?: number;
rpe?: number; // Rate of Perceived Exertion (1-10)
distance?: number; // km
duration?: number; // minutes
completed: boolean;
notes?: string;
}
@@ -34,7 +36,6 @@ export interface IWorkoutSession {
const CompletedSetSchema = new mongoose.Schema({
reps: {
type: Number,
required: true,
min: 0,
max: 1000
},
@@ -48,6 +49,16 @@ const CompletedSetSchema = new mongoose.Schema({
min: 1,
max: 10
},
distance: {
type: Number,
min: 0,
max: 1000 // km
},
duration: {
type: Number,
min: 0,
max: 6000 // minutes
},
completed: {
type: Boolean,
default: false

View File

@@ -1,9 +1,11 @@
import mongoose from 'mongoose';
export interface ISet {
reps: number;
reps?: number;
weight?: number;
rpe?: number; // Rate of Perceived Exertion (1-10)
distance?: number; // km
duration?: number; // minutes
}
export interface IExercise {
@@ -27,8 +29,7 @@ export interface IWorkoutTemplate {
const SetSchema = new mongoose.Schema({
reps: {
type: Number,
required: true,
min: 1,
min: 0,
max: 1000
},
weight: {
@@ -40,6 +41,16 @@ const SetSchema = new mongoose.Schema({
type: Number,
min: 1,
max: 10
},
distance: {
type: Number,
min: 0,
max: 1000 // km
},
duration: {
type: Number,
min: 0,
max: 6000 // minutes
}
});