From 77789d31ca93d4426c439782602813cdc74c5a1a Mon Sep 17 00:00:00 2001 From: AG Date: Sat, 20 Dec 2025 15:37:47 +0200 Subject: [PATCH] Synchronous Fields Reset for Set Logging, Tests fixed --- src/components/Tracker/useTracker.ts | 2 ++ src/hooks/useWorkoutForm.ts | 36 ++++++++++++++++++---------- src/services/i18n.ts | 4 ++-- tests/02_workout_management.spec.ts | 4 ++-- tests/seed.spec.ts | 28 ++++++++++++++-------- 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/components/Tracker/useTracker.ts b/src/components/Tracker/useTracker.ts index 343557c..0cb1db1 100644 --- a/src/components/Tracker/useTracker.ts +++ b/src/components/Tracker/useTracker.ts @@ -140,6 +140,8 @@ export const useTracker = (props: any) => { // Props ignored/removed const updateSelection = async () => { if (selectedExercise) { setSearchQuery(selectedExercise.name); + // Reset form synchronously to clear previous exercise data immediately + form.resetForm(); await form.updateFormFromLastSet(selectedExercise.id, selectedExercise.type, selectedExercise.bodyWeightPercentage); } else { setSearchQuery(''); diff --git a/src/hooks/useWorkoutForm.ts b/src/hooks/useWorkoutForm.ts index fe760df..1cef754 100644 --- a/src/hooks/useWorkoutForm.ts +++ b/src/hooks/useWorkoutForm.ts @@ -41,22 +41,32 @@ export const useWorkoutForm = ({ userId, onSetAdded, onUpdateSet }: UseWorkoutFo setBwPercentage(bodyWeightPercentage ? bodyWeightPercentage.toString() : '100'); const set = await getLastSetForExercise(userId, exerciseId); + + // Use functional updates to only set values if the user hasn't typed anything yet (value is empty string) if (set) { - setWeight(set.weight?.toString() || ''); - setReps(set.reps?.toString() || ''); - setDuration(set.durationSeconds?.toString() || ''); - setDistance(set.distanceMeters?.toString() || ''); - setHeight(set.height?.toString() || ''); - } else { - resetForm(); + setWeight(prev => prev === '' ? (set.weight?.toString() || '') : prev); + setReps(prev => prev === '' ? (set.reps?.toString() || '') : prev); + setDuration(prev => prev === '' ? (set.durationSeconds?.toString() || '') : prev); + setDistance(prev => prev === '' ? (set.distanceMeters?.toString() || '') : prev); + setHeight(prev => prev === '' ? (set.height?.toString() || '') : prev); } - // Clear irrelevant fields - if (exerciseType !== ExerciseType.STRENGTH && exerciseType !== ExerciseType.BODYWEIGHT) setWeight(''); - if (exerciseType !== ExerciseType.STRENGTH && exerciseType !== ExerciseType.BODYWEIGHT && exerciseType !== ExerciseType.PLYOMETRIC) setReps(''); - if (exerciseType !== ExerciseType.CARDIO && exerciseType !== ExerciseType.STATIC) setDuration(''); - if (exerciseType !== ExerciseType.CARDIO && exerciseType !== ExerciseType.LONG_JUMP) setDistance(''); - if (exerciseType !== ExerciseType.HIGH_JUMP) setHeight(''); + // Clear irrelevant fields based on exercise type - this is safe as it clears fields that shouldn't be there + if (exerciseType !== ExerciseType.STRENGTH && exerciseType !== ExerciseType.BODYWEIGHT) { + setWeight(prev => (set && set.weight?.toString() === prev) || prev === '' ? '' : prev); + } + if (exerciseType !== ExerciseType.STRENGTH && exerciseType !== ExerciseType.BODYWEIGHT && exerciseType !== ExerciseType.PLYOMETRIC) { + setReps(prev => (set && set.reps?.toString() === prev) || prev === '' ? '' : prev); + } + if (exerciseType !== ExerciseType.CARDIO && exerciseType !== ExerciseType.STATIC) { + setDuration(prev => (set && set.durationSeconds?.toString() === prev) || prev === '' ? '' : prev); + } + if (exerciseType !== ExerciseType.CARDIO && exerciseType !== ExerciseType.LONG_JUMP) { + setDistance(prev => (set && set.distanceMeters?.toString() === prev) || prev === '' ? '' : prev); + } + if (exerciseType !== ExerciseType.HIGH_JUMP) { + setHeight(prev => (set && set.height?.toString() === prev) || prev === '' ? '' : prev); + } }; const prepareSetData = (selectedExercise: ExerciseDef, isSporadic: boolean = false) => { diff --git a/src/services/i18n.ts b/src/services/i18n.ts index 0c014a9..513f5ff 100644 --- a/src/services/i18n.ts +++ b/src/services/i18n.ts @@ -132,8 +132,8 @@ const translations = { my_plans: 'My Plans', no_plans_yet: 'No workout plans yet.', ask_ai_to_create: 'Ask your AI coach to create one', - create_manually: 'Manually', - create_with_ai: 'With AI', + create_manually: 'Create Plan Manually', + create_with_ai: 'Create Plan with AI', ai_plan_prompt_title: 'Create Plan with AI', ai_plan_prompt_placeholder: 'Any specific requirements? (optional)', generate: 'Generate', diff --git a/tests/02_workout_management.spec.ts b/tests/02_workout_management.spec.ts index 3818513..f954d40 100644 --- a/tests/02_workout_management.spec.ts +++ b/tests/02_workout_management.spec.ts @@ -50,7 +50,7 @@ test.describe('II. Workout Management', () => { await page.getByRole('button', { name: 'Plans' }).first().click(); await page.getByRole('button', { name: 'Create Plan' }).click(); - await page.getByRole('button', { name: 'Manually' }).click(); + await page.getByRole('button', { name: 'Create Plan Manually' }).click(); await expect(page.getByLabel(/Name/i)).toBeVisible({ timeout: 10000 }); await page.getByLabel(`Name`).fill('My New Strength Plan'); @@ -502,7 +502,7 @@ test.describe('II. Workout Management', () => { // VERIFY: Should not appear in Plans Add Exercise selector await page.getByRole('button', { name: 'Plans' }).first().click(); await page.getByRole('button', { name: 'Create Plan' }).click(); - await page.getByRole('button', { name: 'Manually' }).click(); + await page.getByRole('button', { name: 'Create Plan Manually' }).click(); await page.getByRole('button', { name: 'Add Exercise' }).click(); await expect(page.getByRole('button', { name: 'Archive Me' })).not.toBeVisible(); // Close sidesheet - use more robust selector and wait for stability diff --git a/tests/seed.spec.ts b/tests/seed.spec.ts index 97778b5..025af99 100644 --- a/tests/seed.spec.ts +++ b/tests/seed.spec.ts @@ -13,20 +13,28 @@ test.describe('Seed', () => { await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); - // 4. Handle First Time Password Change if it appears - // Wait for either dashboard or change password screen + // 4. Handle transitions (Change Password, Account Setup) + const dashboard = page.getByText(/Free Workout|Свободная тренировка/i).first(); + const changePass = page.getByRole('heading', { name: /Change Password|Смена пароля/i }); + const initAcc = page.getByRole('heading', { name: /Setup Your Account|Настройка аккаунта/i }); + try { - await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 }); - - if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) { - await page.getByLabel('New Password').fill('StrongNewPass123!'); - await page.getByRole('button', { name: /Save|Change/i }).click(); - } + await expect(dashboard.or(changePass).or(initAcc)).toBeVisible({ timeout: 10000 }); + + if (await changePass.isVisible()) { + await page.getByLabel(/New Password|Новый пароль/i).fill('StrongNewPass123!'); + await page.getByRole('button', { name: /Save|Change|Сохранить/i }).click(); + await expect(dashboard.or(initAcc)).toBeVisible({ timeout: 10000 }); + } + + if (await initAcc.isVisible()) { + await page.getByRole('button', { name: /Get Started|Начать работу/i }).click(); + } } catch (e) { - console.log('Timeout waiting for login transition'); + console.log('Transition handling timeout or already reached dashboard'); } // 5. Ensure we are at Dashboard - await expect(page.getByText('Free Workout')).toBeVisible(); + await expect(dashboard).toBeVisible(); }); });