Plan daily and weekly workouts based on goals and muscle groups.
- getMusclePriority
Rank every muscle by how much it needs attention right now, from a real read of the database.
- getExercisesForMuscle
Every exercise linked to a given muscle, via exercise_muscle.
- getLastSession
The most recently logged workout for a given exercise, or null if it's never been logged.
- logWorkout
Log a new workout entry.
- updateWorkout
Update an existing workout entry - e.g. correcting the plan with what was actually done.
- addExercise
Add a new exercise, with the muscles it works (primary/secondary, by whatever rank you give).
- musclePriority
Rank muscles by how much they need attention right now, from a real read of the database: every muscle (including ones never worked at all), and every workout row with its muscles already joined on (see workout()/musclePriority.test.js for the exact query shape this expects). A muscle needs priority once it's past its recovery window, or hasn't been worked often enough this week yet - whichever muscle has gone longest without being worked sorts first.
- copyDatabase
Copy the real database/ directory into an isolated test directory, so insert/update tests have real seed data to work with without ever touching the actual database/ this app runs against.
- workout ⇒
DomItem Generates a table for a workout plan.
- musclePriorityList ⇒
Object.<DomItem> Generates a table ranking muscles by how much they need attention right now.
- logWorkoutForm ⇒
Object Builds the log-workout form's DOM structure. No event wiring here - see exercisePicker.js's own note on why that has to happen after this is attached into the real document and rendered.
- readFormValues
Reads the form's current field values, independent of which button triggered it.
- wireLogWorkoutFormEvents
Wires the form's submit and update buttons - see logWorkoutForm's own note on timing.
- lastSessionDisplay ⇒
DomItem - exercisePicker ⇒
Object Builds the muscle -> exercise picker's DOM structure. No event wiring here - fullAddEventListener needs a complete parentItem chain up to the real document root (it throws otherwise), which a freshly-built, not-yet-attached DomItem doesn't have yet. Call wireExercisePickerEvents once this is attached into the real document and rendered.
- wireExercisePickerEvents
Wires the picker's change events, once it's attached into the real document and rendered - see exercisePicker's own note on why this can't happen at construction time.
- detail ⇒
DomItem Generates a menu with the provided index as the currently selected item.
- addExerciseForm ⇒
Object Builds the add-exercise form's DOM structure. No event wiring here - see exercisePicker.js's own note on why that has to happen after this is attached into the real document and rendered. Primary and secondary are two separate multi-selects (rather than one picker with a per-muscle rank) - a real exercise's muscles split cleanly into those two buckets, and a plain multi-select needs no dynamic add/remove row UI to support picking several of each.
- wireAddExerciseFormEvents
Wires the form's submit button - see addExerciseForm's own note on timing.
- text ⇒
DomItem Create the template of a DomItem
- node ⇒
DomItem Create the template of a DomItem
- navigation ⇒
DomItem Create a nav DomItem
- element ⇒
DomItem Create the template of a DomItem
- responsiveTable ⇒
Object.<DomItem> Generates a menu with the provided index as the currently selected item.
Rank every muscle by how much it needs attention right now, from a real read of the database.
Kind: global constant
| Param | Description |
|---|---|
| today | injectable for testing; defaults to the real current time |
Every exercise linked to a given muscle, via exercise_muscle.
Kind: global constant
| Param |
|---|
| muscleId |
The most recently logged workout for a given exercise, or null if it's never been logged.
Kind: global constant
| Param |
|---|
| exerciseId |
Log a new workout entry.
Kind: global constant
| Param | Description |
|---|---|
| exerciseId | |
| weightEffort | |
| sets | |
| reps | |
| note | |
| date | defaults to today, in the same 'YYYY-MM-DD' shape the rest of the data uses |
| order | where this entry falls among others logged the same day (defaults to first) |
Update an existing workout entry - e.g. correcting the plan with what was actually done.
Kind: global constant
| Param | Description |
|---|---|
| workoutId | |
| changes | any subset of weightEffort/sets/reps/note to change |
Add a new exercise, with the muscles it works (primary/secondary, by whatever rank you give).
Kind: global constant
| Param | Type | Description |
|---|---|---|
| name | ||
| description | ||
| muscleAssignments | Array.<{muscleId: number, rank: number}> |
one row per muscle this exercise works |
Rank muscles by how much they need attention right now, from a real read of the database: every muscle (including ones never worked at all), and every workout row with its muscles already joined on (see workout()/musclePriority.test.js for the exact query shape this expects). A muscle needs priority once it's past its recovery window, or hasn't been worked often enough this week yet - whichever muscle has gone longest without being worked sorts first.
Kind: global constant
| Param | Description |
|---|---|
| muscles | every row from read muscles |
| workoutsWithMuscles | every row from the workouts-joined-to-muscles query, each carrying a .muscles array (the muscles that workout's exercise worked) |
| today | injectable for testing; defaults to the real current time |
Copy the real database/ directory into an isolated test directory, so insert/update tests have real seed data to work with without ever touching the actual database/ this app runs against.
Kind: global constant
| Param |
|---|
| destination |
Generates a table for a workout plan.
Generates a table ranking muscles by how much they need attention right now.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| priorityRows | Array |
musclePriority()'s shape: [{ muscleId, name, daysSinceLastWorked, timesWorkedThisWeek, needsPriority }] |
Builds the log-workout form's DOM structure. No event wiring here - see exercisePicker.js's own note on why that has to happen after this is attached into the real document and rendered.
Reads the form's current field values, independent of which button triggered it.
Kind: global constant
| Param | Type |
|---|---|
| form | Object |
Wires the form's submit and update buttons - see logWorkoutForm's own note on timing.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| form | Object |
|
| onSubmit | function |
({ weightEffort, sets, reps, note, date }) => void, logs a brand new entry |
| onUpdate | function |
({ weightEffort, sets, reps, note, date }) => void, corrects the most recently shown entry |
Kind: global constant
| Param | Type | Description |
|---|---|---|
| session | Object | null |
getLastSession()'s shape, or null if never logged |
Builds the muscle -> exercise picker's DOM structure. No event wiring here - fullAddEventListener needs a complete parentItem chain up to the real document root (it throws otherwise), which a freshly-built, not-yet-attached DomItem doesn't have yet. Call wireExercisePickerEvents once this is attached into the real document and rendered.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| priorityRows | Array |
musclePriority()'s shape, ordered by priority - becomes the muscle dropdown's options, top priority first |
Wires the picker's change events, once it's attached into the real document and rendered - see exercisePicker's own note on why this can't happen at construction time.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| picker | Object |
|
| onMuscleChange | function |
(muscleId: string) => void |
| onExerciseChange | function |
(exerciseId: string) => void |
Generates a menu with the provided index as the currently selected item.
Kind: global constant
| Param | Type |
|---|---|
| currentIndex | number |
Builds the add-exercise form's DOM structure. No event wiring here - see exercisePicker.js's own note on why that has to happen after this is attached into the real document and rendered. Primary and secondary are two separate multi-selects (rather than one picker with a per-muscle rank) - a real exercise's muscles split cleanly into those two buckets, and a plain multi-select needs no dynamic add/remove row UI to support picking several of each.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| muscles | Array |
musclePriority()'s shape (every real muscle, not just priority ones) - becomes both selects' options |
Wires the form's submit button - see addExerciseForm's own note on timing.
Kind: global constant
| Param | Type | Description |
|---|---|---|
| form | Object |
|
| onSubmit | function |
({ name, description, primaryMuscleIds, secondaryMuscleIds }) => void |
Create the template of a DomItem
Kind: global constant
| Param | Type |
|---|---|
| nodeValue | string |
Create the template of a DomItem
Kind: global constant
| Param | Type | Default |
|---|---|---|
| nodeName | string |
|
| nodeValue | string |
|
| [children] | array |
[] |
| [attributes] | object |
{} |
Create a nav DomItem
Kind: global constant
| Param | Type | Default |
|---|---|---|
| [children] | array |
[] |
| [className] | string |
"''" |
| [attributes] | object |
{} |
Create the template of a DomItem
Kind: global constant
| Param | Type | Default |
|---|---|---|
| nodeName | string |
|
| [children] | array |
[] |
| [className] | string |
"''" |
| [attributes] | object |
{} |
Generates a menu with the provided index as the currently selected item.
Kind: global constant
| Param | Type |
|---|---|
| tableRows | Array |
| tableHeadings | Array |
| tableClass | string |