I want to update the exercisesscreen by replacing the clear cache button with a filter button. I also want to allow the user to click on the exercise and it should display  muscle, equipment, diffifculty then have a button for male and female that when they click it redirects to the link.

here is the code.
// services/exerciseService.js
const fs = require('fs');
const path = require('path');
const csv = require('csv-parser');
const Fuse = require('fuse.js');

class ExerciseService {
    constructor() {
        this.exercises = [];
        this.fuse = null;
        this.loadExercises();
    }

    /**
     * Loads exercises from a CSV file and initializes the Fuse.js search index.
     */
    loadExercises() {
        const filePath = path.resolve(__dirname, './Exercises.csv');

        fs.access(filePath, fs.constants.F_OK, (err) => {
            if (err) {
                console.error('Exercises.csv file not found at path:', filePath);
                return;
            }

            fs.createReadStream(filePath)
                .pipe(csv())
                .on('data', (row) => {
                    try {
                        // Parse gender suitability based on presence of URL
                        const genderMale = row.Male && row.Male.trim() !== '';
                        const genderFemale = row.Female && row.Female.trim() !== '';

                        // Clean and parse muscles
                        const muscles = row.Muscle.split(',').map(m => m.trim().toLowerCase());

                        // Clean and parse equipment, excluding any non-equipment terms
                        const equipmentRaw = row.Equipment.split(',').map(e => e.trim().toLowerCase());
                        const validEquipment = ['barbell', 'dumbbell', 'kettlebell', 'machine', 'bodyweight', 'band', 'plate', 'other']; // Define valid equipment terms
                        const equipment = equipmentRaw.filter(e => validEquipment.includes(e));

                        // Parse difficulty
                        const difficulty = row.Difficulty.trim().toLowerCase();

                        // Optional fields with fallback
                        const description = row.Description ? row.Description.trim() : '';
                        const imageUrl = row.ImageURL ? row.ImageURL.trim() : '';
                        const videoUrl = row.VideoURL ? row.VideoURL.trim() : '';

                        const exercise = {
                            name: row.Exercise.trim(),
                            muscles,
                            equipment,
                            difficulty,
                            gender: {
                                male: genderMale,
                                female: genderFemale,
                            },
                            description,
                            imageUrl,
                            videoUrl,
                        };

                        this.exercises.push(exercise);
                    } catch (parseError) {
                        console.error('Error parsing row:', row, 'Error:', parseError);
                    }
                })
                .on('end', () => {
                    console.log(`Loaded ${this.exercises.length} exercises from CSV.`);
                    this.buildFuse();
                })
                .on('error', (err) => {
                    console.error('Error reading Exercises.csv:', err);
                });
        });
    }

    /**
     * Builds the Fuse.js search index for efficient searching.
     */
    buildFuse() {
        if (this.exercises.length === 0) {
            console.warn('No exercises available to build the search index.');
            return;
        }

        const options = {
            keys: ['name', 'muscles', 'equipment', 'description'],
            threshold: 0.3, // Adjust based on desired fuzziness
            includeScore: true,
        };
        this.fuse = new Fuse(this.exercises, options);
        console.log('Fuse.js search index built.');
    }

    /**
     * Searches exercises based on provided filters.
     * @param {object} filters - Search filters.
     * @param {string} filters.search - Search query.
     * @param {string} filters.muscle - Muscle groups.
     * @param {string} filters.equipment - Equipment types.
     * @param {string} filters.difficulty - Difficulty level.
     * @param {string} filters.gender - Gender preference.
     * @param {number} [filters.limit=20] - Maximum number of results.
     * @returns {Array} - Filtered list of exercises.
     */
    searchExercises({ search, muscle, equipment, difficulty, gender, limit = 20 }) {
        let results = this.exercises;
        console.log('Search Filters:', { search, muscle, equipment, difficulty, gender });

        // Search using Fuse.js
        if (search && this.fuse) {
            console.log(`Performing search with query: "${search}"`);
            const fuseResults = this.fuse.search(search);
            results = fuseResults.map(result => result.item);
            console.log(`Exercises after search: ${results.length}`);
        }

        // Filter by muscle
        if (muscle) {
            const muscles = muscle.split(',').map(m => m.trim().toLowerCase());
            console.log(`Filtering by muscles: ${muscles}`);
            results = results.filter(ex => ex.muscles.some(m => muscles.includes(m)));
            console.log(`Exercises after muscle filter: ${results.length}`);
        }

        // Filter by equipment
        if (equipment) {
            const equipments = equipment.split(',').map(e => e.trim().toLowerCase());
            console.log(`Filtering by equipment: ${equipments}`);
            results = results.filter(ex => ex.equipment.some(e => equipments.includes(e)));
            console.log(`Exercises after equipment filter: ${results.length}`);
        }

        // Filter by difficulty
        if (difficulty) {
            const difficultyLower = difficulty.trim().toLowerCase();
            console.log(`Filtering by difficulty: ${difficultyLower}`);
            results = results.filter(ex => ex.difficulty === difficultyLower);
            console.log(`Exercises after difficulty filter: ${results.length}`);
        }

        // Filter by gender
        if (gender) {
            const genderLower = gender.trim().toLowerCase();
            console.log(`Filtering by gender: ${genderLower}`);

            if (genderLower === 'male') {
                results = results.filter(ex => ex.gender.male);
            } else if (genderLower === 'female') {
                results = results.filter(ex => ex.gender.female);
            }
            console.log(`Exercises after gender filter: ${results.length}`);
        }

        // Limit the results
        const finalResults = results.slice(0, limit);
        console.log(`Final number of exercises returned: ${finalResults.length}`);
        return finalResults;
    }
}

module.exports = new ExerciseService();

// components/ExerciseList.js
import React, { useEffect, useState, useContext } from 'react';
import { View, Text, FlatList, Image, StyleSheet, ActivityIndicator, Alert } from 'react-native';
import axios from 'axios';
import { AuthContext } from '../context/AuthContext';

const ExerciseList = () => {
    const { authToken } = useContext(AuthContext);
    const [exercises, setExercises] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        const fetchExercises = async () => {
            try {
                const res = await axios.get('http://10.0.0.203:5000/api/exercises', {
                    headers: {
                        Authorization: authToken
                    }
                });
                setExercises(res.data);
            } catch (err) {
                console.error(err);
                Alert.alert('Error', 'Failed to fetch exercises.');
            } finally {
                setLoading(false);
            }
        };
        fetchExercises();
    }, [authToken]);

    const renderItem = ({ item }) => (
        <View style={styles.itemContainer}>
            {item.imageUrl && <Image source={{ uri: item.imageUrl }} style={styles.image} />}
            <Text style={styles.title}>{item.name}</Text>
            <Text>{item.description}</Text>
            {item.videoUrl && <Text style={styles.link}>Video Tutorial: {item.videoUrl}</Text>}
        </View>
    );

    if (loading) {
        return (
            <View style={styles.loader}>
                <ActivityIndicator size="large" color="#0000ff" />
            </View>
        );
    }

    return (
        <FlatList
            data={exercises}
            keyExtractor={(item) => item._id}
            renderItem={renderItem}
            contentContainerStyle={styles.list}
        />
    );
};

const styles = StyleSheet.create({
    itemContainer: { padding: 10, borderBottomWidth: 1, borderColor: '#ccc' },
    image: { width: '100%', height: 200, marginBottom: 10 },
    title: { fontSize: 18, fontWeight: 'bold' },
    link: { color: 'blue', marginTop: 5 },
    loader: { flex: 1, justifyContent: 'center', alignItems: 'center' },
    list: { paddingBottom: 20 },
});

export default ExerciseList;

// screens/ExercisesScreen.js

import React, { useEffect, useState, useContext, useCallback } from 'react';
import {
    View,
    Text,
    FlatList,
    Image,
    StyleSheet,
    ActivityIndicator,
    Alert,
    TouchableOpacity,
    Linking,
    TextInput,
    RefreshControl,
} from 'react-native';
import axios from 'axios';
import { AuthContext } from '../context/AuthContext';
import debounce from 'lodash.debounce';
import * as SecureStore from 'expo-secure-store';
import { useTheme } from 'react-native-paper'; // Importing useTheme

const ExercisesScreen = () => {
    const { authToken } = useContext(AuthContext);
    const [exercises, setExercises] = useState([]);
    const [loading, setLoading] = useState(true);
    const [searchQuery, setSearchQuery] = useState('');
    const [isRefreshing, setIsRefreshing] = useState(false);

    const theme = useTheme(); // Accessing the theme

    // Define the cache keys
    const CACHE_KEY = 'cachedExercises';
    const CACHE_TIMESTAMP_KEY = 'cachedExercisesTimestamp';
    const MAX_CACHE_AGE = 24 * 60 * 60 * 1000; // 24 hours in milliseconds

    useEffect(() => {
        loadCachedExercises();
    }, [authToken]); // Reload when token changes

    // Debounced fetch function to prevent multiple rapid API calls
    const debouncedFetchExercises = useCallback(
        debounce((query) => {
            fetchExercises(query);
        }, 300),
        [authToken]
    );

    useEffect(() => {
        // Trigger debounced search whenever searchQuery changes
        if (searchQuery.length === 0 || searchQuery.length > 2) { // Trigger search after 3 characters
            debouncedFetchExercises(searchQuery);
        }
    }, [searchQuery, debouncedFetchExercises]);

    /**
     * Load exercises from SecureStore
     */
    const loadCachedExercises = async () => {
        if (!authToken) {
            setLoading(false);
            return;
        }

        try {
            const [cachedData, cachedTimestamp] = await Promise.all([
                SecureStore.getItemAsync(CACHE_KEY),
                SecureStore.getItemAsync(CACHE_TIMESTAMP_KEY),
            ]);

            if (cachedData && cachedTimestamp) {
                const parsedData = JSON.parse(cachedData);
                const timestamp = parseInt(cachedTimestamp, 10);
                const currentTime = Date.now();
                const cacheAge = currentTime - timestamp;

                if (cacheAge < MAX_CACHE_AGE) {
                    setExercises(parsedData);
                    console.log('Loaded exercises from SecureStore.');
                    setLoading(false);
                    return;
                } else {
                    console.log('Cache is stale. Fetching fresh data.');
                }
            } else {
                console.log('No cached data found. Fetching from API.');
            }

            // Fetch fresh data
            fetchExercises();
        } catch (error) {
            console.error('Error loading cached exercises:', error);
            Alert.alert('Error', 'Failed to load cached exercises.');
            fetchExercises();
        }
    };

    /**
     * Fetch exercises from the API
     * @param {string} query - Search query
     */
    const fetchExercises = async (query = '') => {
        if (!authToken) {
            Alert.alert('Authentication Error', 'Please log in to fetch exercises.');
            setLoading(false);
            return;
        }

        console.log('Fetching exercises with token:', authToken);

        try {
            const response = await axios.get('http://10.0.0.203:5000/api/exercises', {
                headers: {
                    Authorization: `Bearer ${authToken}`,
                },
                params: {
                    search: query,
                    limit: 50,
                },
            });

            if (response.status === 200) {
                const fetchedExercises = response.data;
                setExercises(fetchedExercises);

                // Cache the fetched data with a timestamp
                await Promise.all([
                    SecureStore.setItemAsync(CACHE_KEY, JSON.stringify(fetchedExercises)),
                    SecureStore.setItemAsync(CACHE_TIMESTAMP_KEY, Date.now().toString()),
                ]);
                console.log('Fetched exercises from API and cached.');
            } else {
                console.error('Unexpected response status:', response.status);
                Alert.alert('Error', 'Unexpected response from the server.');
            }
        } catch (error) {
            console.error('Error fetching exercises:', error.response ? error.response.data : error.message);
            Alert.alert('Error', 'Failed to fetch exercises from the server.');
        } finally {
            setLoading(false);
            setIsRefreshing(false);
        }
    };

    /**
     * Handle user input in the search bar
     * @param {string} text - Search query text
     */
    const handleSearch = (text) => {
        setSearchQuery(text);
    };

    /**
     * Handle pull-to-refresh action
     */
    const onRefresh = () => {
        setIsRefreshing(true);
        fetchExercises(searchQuery);
    };

    /**
     * Clear cached data manually
     */
    const clearCache = async () => {
        try {
            await SecureStore.deleteItemAsync(CACHE_KEY);
            await SecureStore.deleteItemAsync(CACHE_TIMESTAMP_KEY);
            setExercises([]);
            console.log('Cache cleared successfully.');
            Alert.alert('Success', 'Cache has been cleared.');
        } catch (error) {
            console.error('Error clearing cache:', error);
            Alert.alert('Error', 'Failed to clear cache.');
        }
    };

    /**
     * Render each exercise item
     * @param {object} item - Exercise object
     */
    const renderItem = ({ item }) => (
        <View style={[styles.itemContainer, { borderColor: theme.colors.border }]}>
            {item.imageUrl ? (
                <Image source={{ uri: item.imageUrl }} style={styles.image} resizeMode="cover" />
            ) : (
                <View style={[styles.image, styles.imagePlaceholder, { backgroundColor: theme.colors.surface }]}>
                    <Text style={[styles.imagePlaceholderText, { color: theme.colors.textSecondary }]}>No Image</Text>
                </View>
            )}
            <Text style={[styles.title, { color: theme.colors.text }]}>
                {item.name}
            </Text>
            {item.description ? <Text style={[styles.description, { color: theme.colors.textSecondary }]}>{item.description}</Text> : null}
            {item.videoUrl ? (
                <TouchableOpacity onPress={() => Linking.openURL(item.videoUrl)}>
                    <Text style={[styles.link, { color: theme.colors.primary }]}>Video Tutorial</Text>
                </TouchableOpacity>
            ) : null}
        </View>
    );

    if (loading && exercises.length === 0) {
        return (
            <View style={[styles.loader, { backgroundColor: theme.colors.background }]}>
                <ActivityIndicator size="large" color={theme.colors.primary} />
            </View>
        );
    }

    return (
        <View style={[styles.container, { backgroundColor: theme.colors.background }]}>
            <View style={styles.header}>
                <TextInput
                    style={[
                        styles.searchBar,
                        {
                            backgroundColor: theme.colors.surface,
                            color: theme.colors.text,
                            borderColor: theme.colors.border,
                        },
                    ]}
                    placeholder="Search exercises..."
                    placeholderTextColor={theme.colors.placeholder}
                    value={searchQuery}
                    onChangeText={handleSearch}
                    autoCapitalize="none"
                    autoCorrect={false}
                    clearButtonMode="while-editing"
                />
                <TouchableOpacity
                    style={[
                        styles.clearCacheButton,
                        { backgroundColor: theme.colors.error, opacity: 0.9 },
                    ]}
                    onPress={clearCache}
                >
                    <Text style={[styles.clearCacheButtonText, { color: theme.colors.onSurface }]}>Clear Cache</Text>
                </TouchableOpacity>
            </View>
            <FlatList
                data={exercises}
                keyExtractor={(item, index) => item._id ? item._id : index.toString()} // Fallback to index if _id is missing
                renderItem={renderItem}
                contentContainerStyle={styles.list}
                keyboardShouldPersistTaps="handled"
                refreshControl={
                    <RefreshControl
                        refreshing={isRefreshing}
                        onRefresh={onRefresh}
                        tintColor={theme.colors.primary}
                        colors={[theme.colors.primary, theme.colors.accent]}
                        progressBackgroundColor={theme.colors.surface}
                    />
                }
                ListEmptyComponent={
                    !loading && (
                        <View style={styles.emptyContainer}>
                            <Text style={[styles.emptyText, { color: theme.colors.textSecondary }]}>No exercises found.</Text>
                        </View>
                    )
                }
            />
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    header: {
        flexDirection: 'row',
        alignItems: 'center',
        paddingHorizontal: 10,
        paddingTop: 10,
        paddingBottom: 5,
    },
    searchBar: {
        flex: 1,
        height: 50,
        borderWidth: 1,
        borderRadius: 8,
        marginRight: 10,
        paddingHorizontal: 15,
        fontSize: 16,
    },
    clearCacheButton: {
        height: 50,
        borderRadius: 8,
        justifyContent: 'center',
        alignItems: 'center',
        paddingHorizontal: 15,
    },
    clearCacheButtonText: {
        fontSize: 14,
        fontWeight: 'bold',
    },
    itemContainer: {
        padding: 10,
        borderBottomWidth: 1,
    },
    image: {
        width: '100%',
        height: 200,
        marginBottom: 10,
        borderRadius: 10,
    },
    imagePlaceholder: {
        justifyContent: 'center',
        alignItems: 'center',
    },
    imagePlaceholderText: {
        fontSize: 16,
    },
    title: {
        fontSize: 18,
        fontWeight: 'bold',
    },
    description: {
        marginTop: 5,
        fontSize: 14,
    },
    link: {
        marginTop: 5,
        textDecorationLine: 'underline',
    },
    loader: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
    },
    list: {
        paddingBottom: 20,
    },
    emptyContainer: {
        flex: 1,
        alignItems: 'center',
        marginTop: 50,
    },
    emptyText: {
        fontSize: 16,
    },
});

// Exporting the component as default
export default ExercisesScreen;