This is my current project files. I was planning on webscraping then displaying exercises on the exercisesscreen but I change my mind. I have a Exercises.csv file that I want to load exercises from instead. the headers in the .CSV file are:
Exercise,Muscle,Equipment,Difficulty,Male,Female
I also want the exercisesscreen to have a search bar and exercises to load when you type it should be fast like its indexed.
// models/Exercise.js
const mongoose = require('mongoose');

const ExerciseSchema = new mongoose.Schema({
    name: { type: String, required: true },
    description: String,
    musclesTargeted: [String],
    equipment: [String],
    imageUrl: String,
    videoUrl: String,
    difficulty: { type: String, enum: ['beginner', 'intermediate', 'advanced'], default: 'beginner' },
}, { timestamps: true });

module.exports = mongoose.model('Exercise', ExerciseSchema);

// routes/exercises.js
const express = require('express');
const router = express.Router();
const Exercise = require('../models/Exercise');
const auth = require('../middleware/auth');

// GET /api/exercises
router.get('/', auth, async (req, res) => {
    console.log('GET /api/exercises called');
    const userId = req.user;
    try {
        // Fetch user data
        const User = require('../models/User');
        const user = await User.findById(userId);

        // Example logic: Recommend exercises based on desiredPhysique and fitnessGoals
        let query = {};
        if (user.desiredPhysique === 'muscular') {
            query = { musclesTargeted: { $in: ['chest', 'biceps', 'triceps'] }, difficulty: 'intermediate' };
        } else if (user.desiredPhysique === 'lean') {
            query = { musclesTargeted: { $in: ['legs', 'core'] }, difficulty: 'beginner' };
        }
        // Add more logic based on fitnessGoals

        const exercises = await Exercise.find(query).limit(20);
        console.log(`Fetched ${exercises.length} exercises for user ${userId}`);
        res.json(exercises);
    } catch(err) {
        console.error('Error fetching exercises:', err);
        res.status(500).json({ error: err.message });
    }
});

module.exports = router;

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

const ExercisesScreen = () => {
    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: `Bearer ${authToken}`,
                    },
                });
                setExercises(res.data);
            } catch (err) {
                console.error('Error fetching exercises:', err.response ? err.response.data : err.message);
                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} resizeMode="cover" />
            ) : (
                <View style={[styles.image, styles.imagePlaceholder]}>
                    <Text style={styles.imagePlaceholderText}>No Image</Text>
                </View>
            )}
            <Text style={styles.title}>{item.name}</Text>
            <Text style={styles.description}>{item.description}</Text>
            {item.videoUrl ? (
                <TouchableOpacity onPress={() => Linking.openURL(item.videoUrl)}>
                    <Text style={styles.link}>Video Tutorial</Text>
                </TouchableOpacity>
            ) : null}
        </View>
    );

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

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

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

export default ExercisesScreen;