Files
WerkoutAPI/werkout-frontend/components/onboarding/ScheduleStep.tsx
Trey t 1c61b80731 workout generator audit: rules engine, structure rules, split patterns, injury UX, metadata cleanup
- Add rules_engine.py with quantitative rules for all 8 workout types
- Add quality gate retry loop in generate_single_workout()
- Expand calibrate_structure_rules to all 120 combinations (8 types × 5 goals × 3 sections)
- Wire WeeklySplitPattern DB records into _pick_weekly_split()
- Enforce movement patterns from WorkoutStructureRule in exercise selection
- Add straight-set strength support (single main lift, 4-6 rounds)
- Add modality consistency check for duration-dominant workout types
- Add InjuryStep component to onboarding and preferences
- Add sibling exercise exclusion in regenerate and preview_day endpoints
- Display generator warnings on dashboard
- Expand fix_rep_durations, fix_exercise_flags, fix_movement_pattern_typo
- Add audit_exercise_data and check_rules_drift management commands
- Add Next.js frontend with dashboard, onboarding, preferences, history pages
- Add generator app with ML-powered workout generation pipeline
- 96 new tests across 7 test modules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:07:40 -06:00

98 lines
2.7 KiB
TypeScript

"use client";
import { DAY_NAMES } from "@/lib/types";
interface ScheduleStepProps {
daysPerWeek: number;
preferredDays: number[];
onChange: (data: {
days_per_week?: number;
preferred_days?: number[];
}) => void;
}
const DAYS_OPTIONS = [3, 4, 5, 6];
export function ScheduleStep({
daysPerWeek,
preferredDays,
onChange,
}: ScheduleStepProps) {
const toggleDay = (dayIndex: number) => {
if (preferredDays.includes(dayIndex)) {
onChange({
preferred_days: preferredDays.filter((d) => d !== dayIndex),
});
} else {
onChange({
preferred_days: [...preferredDays, dayIndex],
});
}
};
return (
<div>
<h2 className="text-2xl font-bold text-zinc-100 mb-2">
Your Schedule
</h2>
<p className="text-zinc-400 mb-8">
How often do you want to work out, and which days work best for you?
</p>
{/* Days per week */}
<div className="mb-8">
<h3 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-3">
Days Per Week
</h3>
<div className="flex gap-3">
{DAYS_OPTIONS.map((num) => {
const isSelected = daysPerWeek === num;
return (
<button
key={num}
onClick={() => onChange({ days_per_week: num })}
className={`flex-1 py-3 rounded-lg text-lg font-bold transition-all duration-150 cursor-pointer ${
isSelected
? "bg-accent text-black"
: "bg-zinc-800 text-zinc-300 hover:bg-zinc-700"
}`}
>
{num}
</button>
);
})}
</div>
</div>
{/* Preferred days */}
<div>
<h3 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-3">
Preferred Days
</h3>
<div className="flex gap-2">
{DAY_NAMES.map((name, index) => {
const isSelected = preferredDays.includes(index);
return (
<button
key={index}
onClick={() => toggleDay(index)}
className={`flex-1 py-3 rounded-lg text-sm font-semibold transition-all duration-150 cursor-pointer ${
isSelected
? "bg-accent text-black"
: "bg-zinc-800 text-zinc-300 hover:bg-zinc-700"
}`}
>
{name}
</button>
);
})}
</div>
<p className="text-sm text-zinc-500 mt-3">
Select the days you prefer to train. This helps us schedule rest days
optimally.
</p>
</div>
</div>
);
}