fix: prevent form reset on error, add multi-select for goal/activity/injury
- Remove profileNextStep(1) from saveProfile catch block so users stay on current step when an error occurs instead of being sent back to step 1 - Convert Goal, Activity Level, and Injury Area fields from single-select (radio/dropdown) to multi-select checkboxes with comma-separated storage - Add validateMultiEnum backend validation for comma-separated enum values - Update trainer.js filterByInjury and goal checks for multi-value support - Update dietitian.js TDEE, calorie, and water calculations for multi-values Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -406,9 +406,16 @@ function pickRandom(arr, count) {
|
||||
return shuffled.slice(0, Math.min(count, arr.length));
|
||||
}
|
||||
|
||||
function hasGoal(profile, goalValue) {
|
||||
const goal = profile.goal || "maintain";
|
||||
return goal.split(",").map((s) => s.trim()).includes(goalValue);
|
||||
}
|
||||
|
||||
function filterByInjury(exercises, injuryArea) {
|
||||
if (!injuryArea || injuryArea === "none") return exercises;
|
||||
return exercises.filter((e) => !e.contraindicated_injuries.includes(injuryArea));
|
||||
const areas = String(injuryArea).split(",").map((s) => s.trim()).filter((s) => s && s !== "none");
|
||||
if (areas.length === 0) return exercises;
|
||||
return exercises.filter((e) => !areas.some((area) => e.contraindicated_injuries.includes(area)));
|
||||
}
|
||||
|
||||
function filterByConditions(exercises, profile) {
|
||||
@@ -743,7 +750,8 @@ function buildInjuryNote(profile) {
|
||||
mild: "mild", moderate: "moderate", severe: "severe",
|
||||
};
|
||||
|
||||
const areaName = areaNames[profile.injury_area] || profile.injury_area;
|
||||
const areas = String(profile.injury_area).split(",").map((s) => s.trim()).filter((s) => s && s !== "none");
|
||||
const areaName = areas.map((a) => areaNames[a] || a).join(", ");
|
||||
const severityName = severityNames[profile.injury_severity] || "mild";
|
||||
let note = `Program adapted for ${severityName} ${areaName} injury.`;
|
||||
|
||||
@@ -872,7 +880,7 @@ function buildCardioDay(dayNumber, dayName, focus, profile, week) {
|
||||
const bodyType = profile.body_type || "mesomorph";
|
||||
let exercises = [];
|
||||
|
||||
if ((bodyType === "endomorph" || profile.goal === "lose_weight") && !profile.heart_condition) {
|
||||
if ((bodyType === "endomorph" || hasGoal(profile, "lose_weight")) && !profile.heart_condition) {
|
||||
const safeHiit = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.hiit, injuryArea), profile), profile), location);
|
||||
const safeCardio = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.cardio, injuryArea), profile), profile), location);
|
||||
exercises = [...pickRandom(safeHiit, 4), ...pickRandom(safeCardio, 1)];
|
||||
@@ -1120,7 +1128,6 @@ function generateWheelchairProgram(profile, week) {
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
function applyGoalAdjustments(days, profile, week) {
|
||||
const goal = profile.goal || "maintain";
|
||||
const bodyType = profile.body_type || "mesomorph";
|
||||
const location = profile.workout_location || "gym";
|
||||
|
||||
@@ -1130,7 +1137,7 @@ function applyGoalAdjustments(days, profile, week) {
|
||||
let modified = { ...day, exercises: [...day.exercises] };
|
||||
|
||||
// For lose_weight: add cardio to strength days
|
||||
if (goal === "lose_weight" && day.type === "strength" && !profile.heart_condition) {
|
||||
if (hasGoal(profile, "lose_weight") && day.type === "strength" && !profile.heart_condition) {
|
||||
const injuryArea = profile.has_injury ? (profile.injury_area || "none") : "none";
|
||||
let safeCardio = filterByLocation(filterByEquipment(filterByConditions(filterByInjury(EXERCISES.cardio, injuryArea), profile), profile), location);
|
||||
if (safeCardio.length > 0) {
|
||||
@@ -1154,7 +1161,7 @@ function applyGoalAdjustments(days, profile, week) {
|
||||
}
|
||||
|
||||
// Gain weight: remove excess cardio from strength days
|
||||
if (goal === "gain_weight") {
|
||||
if (hasGoal(profile, "gain_weight")) {
|
||||
modified.exercises = modified.exercises.filter((e) => {
|
||||
return !EXERCISES.cardio.some((c) => c.name === e.name);
|
||||
});
|
||||
@@ -1165,11 +1172,10 @@ function applyGoalAdjustments(days, profile, week) {
|
||||
}
|
||||
|
||||
function adjustCardioRestDays(days, profile, week) {
|
||||
const goal = profile.goal || "maintain";
|
||||
const bodyType = profile.body_type || "mesomorph";
|
||||
let cardioDaysNeeded = 0;
|
||||
|
||||
if (goal === "lose_weight" && !profile.heart_condition) cardioDaysNeeded = 2;
|
||||
if (hasGoal(profile, "lose_weight") && !profile.heart_condition) cardioDaysNeeded = 2;
|
||||
else if (bodyType === "endomorph" && !profile.heart_condition) cardioDaysNeeded = 1;
|
||||
|
||||
let converted = 0;
|
||||
|
||||
Reference in New Issue
Block a user