@@ -201,7 +201,7 @@ export default function PlanSetupForm({
201201 const hasExistingCalibration = useRef ( false ) ;
202202 // Track whether we've loaded settings from the server (to prevent race-type defaults from overriding them)
203203 const settingsLoadedRef = useRef ( false ) ;
204- const initialRaceTypeRef = useRef < string | null > ( null ) ;
204+
205205
206206 const [ message , setMessage ] = useState ( '' ) ;
207207 const [ formErrors , setFormErrors ] = useState < Record < string , string > > ( { } ) ;
@@ -265,17 +265,16 @@ export default function PlanSetupForm({
265265 const shapePercent = propShapePercent > 0 ? propShapePercent : ( internalStatsData ?. marathonShape ?. shape || 0 ) ;
266266
267267 // Auto-initialize startWeeklyMileage from the user's last 4 weeks of running
268- // Skip in settings mode — the goal's saved value will be loaded instead
268+ // startWeeklyMileage is not persisted in the Goal model, so we always derive it
269269 useEffect ( ( ) => {
270- if ( mode === 'settings' ) return ;
271270 if ( ! startMileageInitialized . current && internalStatsData ?. avgWeeklyKmLast4Weeks > 0 ) {
272271 const avg = internalStatsData . avgWeeklyKmLast4Weeks ;
273272 // Round down to nearest 5 km for a clean slider value
274273 const rounded = Math . floor ( avg / 5 ) * 5 ;
275274 setStartWeeklyMileage ( Math . max ( 5 , rounded ) ) ;
276275 startMileageInitialized . current = true ;
277276 }
278- } , [ internalStatsData , mode ] ) ;
277+ } , [ internalStatsData ] ) ;
279278
280279 // Fetch existing settings (for settings mode)
281280 const { data : settingsData } = useQuery ( {
@@ -393,28 +392,30 @@ export default function PlanSetupForm({
393392 ? ( parseInt ( durationWeeks ) || 12 )
394393 : Math . max ( 4 , Math . floor ( ( new Date ( raceDate ) . getTime ( ) - new Date ( planStartDate ) . getTime ( ) ) / msPerWeek ) ) ;
395394
395+ // Track whether the user has explicitly changed raceType after settings loaded
396+ const userChangedRaceTypeRef = useRef ( false ) ;
397+ // Track whether the user has explicitly changed weeklyMileage or raceType after settings loaded
398+ const userChangedVolumeRef = useRef ( false ) ;
399+
396400 const maxLongRunLoadedRef = useRef ( false ) ;
397401 useEffect ( ( ) => {
398- // In settings mode, skip the first recalculation — the API value was loaded
399- if ( mode === 'settings' && settingsLoadedRef . current && ! maxLongRunLoadedRef . current ) {
400- maxLongRunLoadedRef . current = true ;
401- return ;
402+ // In settings mode, only recalculate maxLongRunKm when the user explicitly changed volume/race
403+ if ( mode === 'settings' ) {
404+ if ( ! userChangedVolumeRef . current ) {
405+ return ; // Don't recalculate from defaults — API value is correct
406+ }
402407 }
403408 setMaxLongRunKm ( getDefaultMaxLongRunKm ( raceType , weeklyMileage ) ) ;
404409 } , [ raceType , weeklyMileage , mode ] ) ;
405410
406411 useEffect ( ( ) => {
407412 // In settings mode, only apply race-type defaults when the user explicitly changes the race type.
408413 // The settingsData effect already loaded the correct saved values from the API.
409- if ( mode === 'settings' && ! settingsLoadedRef . current ) return ;
410- if ( mode === 'settings' && initialRaceTypeRef . current !== null ) {
411- // First raceType change from goalsData — skip and clear the guard
412- if ( raceType === initialRaceTypeRef . current ) {
413- initialRaceTypeRef . current = null ;
414- return ;
414+ // We block ALL default overwrites until the user explicitly changes raceType.
415+ if ( mode === 'settings' ) {
416+ if ( ! userChangedRaceTypeRef . current ) {
417+ return ; // Skip — settings were loaded from API, no user change yet
415418 }
416- // Different raceType — user changed it, allow defaults to apply
417- initialRaceTypeRef . current = null ;
418419 }
419420 let defaults = getRaceDefaults ( raceType ) ;
420421 if ( effectiveVO2max > 0 ) {
@@ -436,6 +437,8 @@ export default function PlanSetupForm({
436437 setTargetLaps ( defaults . targetLaps ) ;
437438 }
438439 setTriGoalTimeSeconds ( null ) ;
440+ // Mark volume as changed too, so maxLongRunKm recalculates on next render
441+ userChangedVolumeRef . current = true ;
439442 } , [ raceType , mode , computedPlanWeeks ] ) ;
440443
441444 // Auto-prefill threshold values from calibration data while still allowing manual overrides.
@@ -497,7 +500,7 @@ export default function PlanSetupForm({
497500 if ( goalsData ?. goals ?. length > 0 ) {
498501 const activeGoal = goalsData . goals . find ( ( g : any ) => g . isActive ) ;
499502 if ( activeGoal ) {
500- initialRaceTypeRef . current = activeGoal . raceType || 'MARATHON' ;
503+
501504 setGoalName ( activeGoal . name || 'My Race' ) ;
502505 setRaceType ( activeGoal . raceType || 'MARATHON' ) ;
503506 if ( activeGoal . raceDate ) {
@@ -875,7 +878,13 @@ export default function PlanSetupForm({
875878 goalName = { goalName }
876879 setGoalName = { setGoalName }
877880 raceType = { raceType }
878- setRaceType = { setRaceType }
881+ setRaceType = { ( val : string ) => {
882+ if ( mode === 'settings' && settingsLoadedRef . current ) {
883+ userChangedRaceTypeRef . current = true ;
884+ userChangedVolumeRef . current = true ;
885+ }
886+ setRaceType ( val ) ;
887+ } }
879888 raceDate = { raceDate }
880889 setRaceDate = { setRaceDate }
881890 planStartDate = { planStartDate }
@@ -1004,10 +1013,20 @@ export default function PlanSetupForm({
10041013 strengthPerWeek = { strengthPerWeek }
10051014 setStrengthPerWeek = { setStrengthPerWeek }
10061015 weeklyMileage = { weeklyMileage }
1007- setWeeklyMileage = { setWeeklyMileage }
1016+ setWeeklyMileage = { ( val : number ) => {
1017+ if ( mode === 'settings' && settingsLoadedRef . current ) {
1018+ userChangedVolumeRef . current = true ;
1019+ }
1020+ setWeeklyMileage ( val ) ;
1021+ } }
10081022 raceType = { raceType }
10091023 maxLongRunKm = { maxLongRunKm }
1010- setMaxLongRunKm = { setMaxLongRunKm }
1024+ setMaxLongRunKm = { ( val : number ) => {
1025+ if ( mode === 'settings' && settingsLoadedRef . current ) {
1026+ userChangedVolumeRef . current = true ;
1027+ }
1028+ setMaxLongRunKm ( val ) ;
1029+ } }
10111030 taperWeeks = { taperWeeks }
10121031 setTaperWeeks = { setTaperWeeks }
10131032 peakWeeks = { peakWeeks }
0 commit comments