Skip to content

Enhance exercise filtering and tracking features#18

Merged
brylie merged 42 commits intomainfrom
add-exercise-filters
Mar 31, 2025
Merged

Enhance exercise filtering and tracking features#18
brylie merged 42 commits intomainfrom
add-exercise-filters

Conversation

@brylie
Copy link
Copy Markdown
Owner

@brylie brylie commented Mar 31, 2025

Closes #17

User description

Introduce new filtering capabilities for exercises, including a dedicated ExerciseFilter component and improved type safety with the ExerciseFilters interface. Update workout generation logic and enhance styling consistency across components. Additionally, update dependencies and streamline configurations for better performance.


PR Type

Enhancement, Tests, Documentation, Configuration changes, Dependencies, Formatting


Description

  • Introduced new filtering capabilities for exercises with the ExerciseFilter component and enhanced type safety using the ExerciseFilters interface.

  • Standardized enums for muscles, joints, and equipment across exercise data files for consistency.

  • Added extensive unit and end-to-end tests for filtering functionality, workout generation, and exercise library.

  • Created new modules for Muscles, Equipment, and Joints with enums, registries, and helper functions.

  • Updated dependencies, including @playwright/test and daisyui, and locked versions for consistency.

  • Integrated ExerciseFilter into workout generation and exercise library pages, improving UI and dynamic filtering.

  • Updated Playwright configuration for improved testing performance and reliability.

  • Enhanced badge styling consistency across components.

  • Updated documentation to reflect changes and removed outdated instructions.


Changes walkthrough 📝

Relevant files
Enhancement
15 files
yoga.ts
Standardized muscle and joint enums in yoga exercise data.

app/src/lib/exercise_data/yoga.ts

  • Updated imports to use new module paths for Muscles and Joints.
  • Standardized muscle and joint enum values to uppercase format.
  • +91/-90 
    dumbbells.ts
    Standardized muscle and equipment enums in dumbbell exercise data.

    app/src/lib/exercise_data/dumbbells.ts

  • Updated imports to use new module paths for Muscles and Equipment.
  • Standardized muscle and equipment enum values to uppercase format.
  • +66/-67 
    bodyweight.ts
    Standardized muscle and joint enums in bodyweight exercise data.

    app/src/lib/exercise_data/bodyweight.ts

  • Updated imports to use new module paths for Muscles and Joints.
  • Standardized muscle and joint enum values to uppercase format.
  • +31/-30 
    pilates.ts
    Standardized muscle enums in Pilates exercise data.           

    app/src/lib/exercise_data/pilates.ts

  • Updated imports to use new module paths for Muscles.
  • Standardized muscle enum values to uppercase format.
  • +22/-22 
    machines.ts
    Standardized muscle and equipment enums in machine exercise data.

    app/src/lib/exercise_data/machines.ts

  • Updated imports to use new module paths for Muscles and Equipment.
  • Standardized muscle and equipment enum values to uppercase format.
  • +28/-27 
    equipment.ts
    Added equipment enum and registry with helper functions. 

    app/src/lib/equipment.ts

  • Introduced Equipment enum and equipmentRegistry for managing equipment
    metadata.
  • Added helper functions for accessing equipment details.
  • +159/-0 
    kettlebell.ts
    Standardized muscle and equipment enums in kettlebell exercise data.

    app/src/lib/exercise_data/kettlebell.ts

  • Updated imports to use new module paths for Muscles and Equipment.
  • Standardized muscle and equipment enum values to uppercase format.
  • +18/-17 
    muscles.ts
    Added muscles enum and registry with helper functions.     

    app/src/lib/muscles.ts

  • Introduced Muscles enum and musclesRegistry for managing muscle
    metadata.
  • Added helper functions for accessing muscle details.
  • +130/-0 
    types.ts
    Updated type definitions and added ExerciseFilters interface.

    app/src/lib/types.ts

  • Updated type definitions to use new Muscles and Equipment modules.
  • Added ExerciseFilters interface for filtering exercises.
  • +12/-9   
    calisthenics.ts
    Update muscle references in calisthenics exercises.           

    app/src/lib/exercise_data/calisthenics.ts

  • Updated Muscles enum references to use uppercase constants.
  • Improved type safety and consistency in exercise definitions.
  • +6/-5     
    joints.ts
    Add joints module with enums and utilities.                           

    app/src/lib/joints.ts

  • Introduced Joints enum and JointDetails interface.
  • Added jointsRegistry and helper functions for joint details.
  • Provided a flat jointsList for convenience.
  • +84/-0   
    exercises.ts
    Add filtering and random selection for exercises.               

    app/src/lib/exercises.ts

  • Added filterExercises function to filter exercises by muscles and
    equipment.
  • Introduced getFilteredRandomExercises for generating random filtered
    workouts.
  • Improved modularity and filtering capabilities.
  • +43/-2   
    +page.svelte
    Add exercise filtering to workout generation page.             

    app/src/routes/workout/+page.svelte

  • Integrated ExerciseFilter component for workout generation.
  • Added filtering logic for generating workouts based on user-selected
    criteria.
  • Improved state management with $state syntax.
  • +45/-25 
    ExerciseFilter.svelte
    Add ExerciseFilter component for dynamic filtering.           

    app/src/lib/components/ExerciseFilter.svelte

  • Created ExerciseFilter component for filtering exercises by muscles
    and equipment.
  • Added UI elements for selecting filters dynamically.
  • Integrated badges to display active filter counts.
  • +101/-0 
    +page.svelte
    Add filtering functionality to exercise library page.       

    app/src/routes/exercises/+page.svelte

  • Integrated ExerciseFilter component for filtering exercises.
  • Added dynamic filtering logic for the exercise library.
  • Improved UI with badges and sorted filtered exercises.
  • +42/-8   
    Tests
    9 files
    ExerciseFilter.svelte.test.ts
    Added unit tests for ExerciseFilter component functionality.

    app/src/lib/components/ExerciseFilter.svelte.test.ts

  • Added unit tests for the ExerciseFilter component.
  • Verified functionality for filter toggling, badge counts, and filter
    application.
  • +232/-0 
    workout-generator.test.ts
    Added E2E tests for workout generator with filters.           

    app/e2e/workout-generator.test.ts

  • Added end-to-end tests for the workout generator page.
  • Verified functionality for generating workouts with muscle and
    equipment filters.
  • +144/-0 
    exercises.test.ts
    Added unit tests for exercise filtering and randomization.

    app/src/lib/exercises.test.ts

  • Added tests for filtering exercises by muscle and equipment.
  • Verified functionality for random exercise generation with filters.
  • +108/-6 
    exercises.test.ts
    Added E2E tests for exercise library filtering.                   

    app/e2e/exercises.test.ts

  • Added end-to-end tests for the exercise library page.
  • Verified filtering functionality by muscle and equipment.
  • +110/-0 
    equipment.test.ts
    Add unit tests for equipment module functionality.             

    app/src/lib/equipment.test.ts

  • Added comprehensive unit tests for equipment module.
  • Tested getEquipmentDetails, getEquipmentDetailsForTypes, and
    equipmentList functions.
  • Verified Equipment enum contains expected values.
  • +102/-0 
    types.test.ts
    Update and expand tests for types module.                               

    app/src/lib/types.test.ts

  • Updated tests to use corrected enum values for Muscles and Equipment.
  • Added tests for metrics property in ExerciseDetails.
  • Enhanced test coverage for Workout and WorkoutItem types.
  • +35/-10 
    muscles.test.ts
    Add unit tests for muscles module functionality.                 

    app/src/lib/muscles.test.ts

  • Added unit tests for muscles module.
  • Tested getMuscleDetails, getMuscleDetailsForTypes, and musclesList
    functions.
  • Verified Muscles enum contains expected values.
  • +79/-0   
    database.test.ts
    Add migration tests for database module.                                 

    app/src/lib/database.test.ts

  • Added tests for migrateExerciseV1ToV2 function.
  • Verified migration handles full, partial, and already migrated data
    correctly.
  • +67/-2   
    joints.test.ts
    Add unit tests for joints module functionality.                   

    app/src/lib/joints.test.ts

  • Added unit tests for joints module.
  • Tested getJointDetails, getJointDetailsForTypes, and jointsList
    functions.
  • Verified Joints enum contains expected values.
  • +77/-0   
    Configuration changes
    2 files
    app.css
    Integrated daisyui plugin into Tailwind CSS configuration.

    app/src/app.css

    • Added daisyui plugin to Tailwind CSS configuration.
    +1/-0     
    playwright.config.ts
    Update Playwright configuration for server and timeout.   

    app/playwright.config.ts

  • Updated Playwright server configuration to use pnpm commands.
  • Changed default port to 4174 and enabled server reuse.
  • Added a global timeout for tests.
  • +6/-3     
    Dependencies
    2 files
    pnpm-lock.yaml
    Update dependencies and lock file.                                             

    app/pnpm-lock.yaml

  • Updated dependencies, including @playwright/test and added daisyui.
  • Locked versions for consistent dependency management.
  • +9/-1     
    package.json
    Update package.json with new dependencies.                             

    app/package.json

  • Updated @playwright/test to version 1.51.0.
  • Added daisyui dependency for enhanced UI components.
  • +2/-1     
    Formatting
    1 files
    WorkoutItem.svelte
    Update badge styling in WorkoutItem component.                     

    app/src/lib/components/WorkoutItem.svelte

  • Updated class names for muscle and equipment badges.
  • Improved consistency in badge styling across components.
  • +2/-2     
    Documentation
    1 files
    copilot-instructions.md
    Update Copilot instructions for Svelte 5.                               

    .github/copilot-instructions.md

  • Removed outdated TypeScript import instructions.
  • Added note about using Svelte 5 runes syntax.
  • +2/-5     
    Additional files
    7 files
    workout-history.test.ts +0/-8     
    database.migration.test.ts +0/-70   
    enums.test.ts +0/-45   
    enums.ts +0/-63   
    equipmentData.test.ts +0/-112 
    equipmentData.ts +0/-127 
    +layout.svelte +0/-1     

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • brylie added 30 commits March 31, 2025 11:34
    …erciseFilters interface for improved type safety
    …, and equipment for improved styling consistency
    @brylie brylie requested a review from Copilot March 31, 2025 14:58
    Copy link
    Copy Markdown

    Copilot AI left a comment

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Pull Request Overview

    This PR enhances exercise filtering and tracking by updating exercise data, adding a dedicated ExerciseFilter component, and refining workout generation and dependency configurations for better performance.

    • Updated muscle and joint enum naming in bodyweight exercise data
    • Removed legacy equipment data and tests and replaced them with new equipment modules
    • Added migration support for completed exercises and enhanced e2e tests for filtering features

    Reviewed Changes

    Copilot reviewed 32 out of 37 changed files in this pull request and generated no comments.

    Show a summary per file
    File Description
    app/src/lib/exercise_data/bodyweight.ts Updated import paths and switched to uppercase enum keys for muscles and joints
    app/src/lib/equipment*.ts Replaced legacy equipment modules with new, type-safe implementations and tests
    app/src/lib/database.test.ts Added migration tests for converting V1 completed exercises to V2
    app/src/lib/components/ExerciseFilter.svelte.test.ts Introduced comprehensive tests for the new ExerciseFilter component
    playwright.config.ts & e2e tests Updated configuration and e2e tests to align with new filtering and UI changes
    .github/copilot-instructions.md Updated instructions to reflect Svelte 5 runes syntax usage
    Files not reviewed (5)
    • app/package.json: Language not supported
    • app/pnpm-lock.yaml: Language not supported
    • app/src/app.css: Language not supported
    • app/src/lib/components/ExerciseFilter.svelte: Language not supported
    • app/src/lib/components/WorkoutItem.svelte: Language not supported
    Comments suppressed due to low confidence (3)

    app/src/lib/components/ExerciseFilter.svelte.test.ts:105

    • Consider expanding tests for equipment filters to cover all available equipment options rather than only a subset, ensuring comprehensive UI coverage.
    const filterInput = container.querySelector(`#equipment-filter-${Equipment.DUMBBELLS}`);
    

    .github/copilot-instructions.md:7

    • Ensure all documentation and example code snippets are updated to consistently use Svelte 5 runes syntax to avoid confusion for new contributors.
    This project uses Svelte 5. Use the Svelte 5 runes syntax instead of the older `$:` syntax.
    

    app/src/lib/database.test.ts:205

    • [nitpick] Avoid using type casting in migration tests; consider refining the migration function's type definitions so that tests can pass a properly typed V2 exercise directly.
    const result = migrateExerciseV1ToV2(exerciseV2 as unknown as CompletedExerciseV1);
    

    @qodo-code-review
    Copy link
    Copy Markdown

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Import Organization

    The import for Muscles is using an absolute path ($lib/muscles) while Joints uses a relative path (../joints). Consider standardizing import paths for consistency.

    import { Joints } from '../joints';
    import { Muscles } from '$lib/muscles';

    @qodo-code-review
    Copy link
    Copy Markdown

    qodo-code-review Bot commented Mar 31, 2025

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix reactive state update
    Suggestion Impact:The commit implemented the exact suggestion by replacing the direct property assignments (filters.muscles and filters.equipment) with a complete object replacement (filters = {...}) in the handleFilterChange function

    code diff:

    +	function handleFilterChange(newFilters: ExerciseFilters) {
    +		filters = {
    +			muscles: newFilters.muscles,
    +			equipment: newFilters.equipment,
    +		};
    +	}

    When using Svelte's $state for reactive variables, direct property assignments
    won't trigger reactivity properly. You should replace the entire object to
    ensure proper reactivity when filters change.

    app/src/routes/workout/+page.svelte [34-37]

     function handleFilterChange(newFilters: ExerciseFilters) {
    -    filters.muscles = newFilters.muscles;
    -    filters.equipment = newFilters.equipment;
    +    filters = {
    +        muscles: newFilters.muscles,
    +        equipment: newFilters.equipment
    +    };
     }

    [Suggestion has been applied]

    Suggestion importance[1-10]: 9

    __

    Why: This is a critical fix for Svelte's reactivity system. With $state variables, assigning to properties doesn't trigger proper reactivity, so replacing the entire object is necessary to ensure UI updates correctly when filters change.

    High
    Check all cards for filter

    The test only checks the first workout card for dumbbells equipment, but the
    filter should apply to all generated workout cards. You should verify that at
    least one of all cards has dumbbells, not just the first one.

    app/e2e/workout-generator.test.ts [67-71]

     // Verify at least one exercise has Dumbbells
    -const firstCard = workoutCards.first();
    -const equipmentLabels = await firstCard.locator('.exercise-equipment').allInnerTexts();
    -const hasDumbbells = equipmentLabels.some(label => label.toLowerCase().includes('dumbbells'));
    +let hasDumbbells = false;
    +for (let i = 0; i < 2; i++) {
    +  const card = workoutCards.nth(i);
    +  const equipmentLabels = await card.locator('.exercise-equipment').allInnerTexts();
    +  if (equipmentLabels.some(label => label.toLowerCase().includes('dumbbells'))) {
    +    hasDumbbells = true;
    +    break;
    +  }
    +}
     expect(hasDumbbells).toBeTruthy();
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    __

    Why: The current test only checks the first workout card for dumbbells equipment, but the filter should apply to all generated cards. The improved code correctly loops through all cards to verify the filter is working properly, which is more thorough and reliable.

    Medium
    Fix equipment filter logic

    The equipment filter logic has a potential bug when an exercise has no equipment
    property or an empty array. The current implementation will filter out exercises
    with no equipment when an equipment filter is applied, but these exercises might
    still be valid for the user's workout.

    app/src/lib/exercises.ts [69-86]

     export function filterExercises(filters: ExerciseFilters): ExerciseDetails[] {
       return allExercises.filter(exercise => {
         // Check muscle filter if provided
         if (filters.muscles?.length) {
           if (!filters.muscles.some(muscle => exercise.muscles.includes(muscle))) {
             return false;
           }
         }
         
         // Check equipment filter if provided
         if (filters.equipment?.length) {
    -      if (!exercise.equipment?.some(eq => filters.equipment!.includes(eq))) {
    +      // If exercise has no equipment, it shouldn't be filtered by equipment
    +      if (!exercise.equipment || exercise.equipment.length === 0) {
    +        return false;
    +      }
    +      if (!exercise.equipment.some(eq => filters.equipment!.includes(eq))) {
             return false;
           }
         }
         
         return true;
       });
     }

    [To ensure code accuracy, apply this suggestion manually]

    Suggestion importance[1-10]: 5

    __

    Why: The suggestion identifies a logical issue in the equipment filter, but the improved code has a bug itself. It would filter out bodyweight exercises (which have no equipment) when equipment filters are applied, which is likely not the intended behavior.

    Low
    General
    Remove redundant function

    The getEquipment() function is redundant since it does exactly the same thing as
    getEquipmentDetails(). Consider removing this duplicate function to avoid
    confusion and maintain a cleaner API.

    app/src/lib/equipment.ts [132-134]

    -export function getEquipment(type: Equipment): EquipmentDetails {
    -  return equipmentRegistry[type];
    +/**
    + * Helper function to get equipment details by type.
    + * Use this function in the UI when you need to display equipment metadata.
    + * @param equipmentType The equipment type to get details for
    + * @returns The equipment details including name and description
    + */
    +export function getEquipmentDetails(equipmentType: Equipment): EquipmentDetails {
    +  return equipmentRegistry[equipmentType];
     }
    • Apply this suggestion
    Suggestion importance[1-10]: 7

    __

    Why: The suggestion correctly identifies that the getEquipment() function is redundant as it performs exactly the same operation as getEquipmentDetails(). Removing this duplicate function would improve code maintainability and reduce potential confusion for developers.

    Medium
    • Update

    @brylie brylie merged commit c6701a5 into main Mar 31, 2025
    1 check passed
    @brylie brylie deleted the add-exercise-filters branch March 31, 2025 16:01
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    Exercise Filter Component for Library and Workout Generator

    2 participants