Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 86 additions & 15 deletions src/pages/ExcerciseDetail.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,112 @@
import React, { useEffect, useState } from 'react'
import {useParams} from 'react-router-dom'
import {Box} from '@mui/material'
import {Box, Typography, Alert, CircularProgress} from '@mui/material'
import {fetchData, exerciseOptions, youtubeOptions} from '../utils/fetchData'
import Detail from '../components/Detail'
import ExerciseVideos from '../components/ExerciseVideos'
import SimilarExercises from '../components/SimilarExercises'
import Loader from '../components/Loader'

const ExcerciseDetail = () => {
const [exerciseDetails, setExerciseDetails] = useState({})
const [exerciseVideos, setExerciseVideos] = useState([])
const [targetMuscleExercises, setTargetMuscleExercisesData] = useState([])
const [equipmentExercises, setEquipmentExercises] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState(null)
const {id} = useParams()

useEffect(() =>{
const fetchExerciseData = async() =>{
const exerciseDbUrl = 'https://exercisedb.p.rapidapi.com'
const youtubeSearchUrl = 'https://youtube-search-and-download.p.rapidapi.com'

const exerciseDetailData = await fetchData(`${exerciseDbUrl}/exercises/exercise/${id}`, exerciseOptions)
setExerciseDetails(exerciseDetailData)
const exerciseVideoData = await fetchData(`${youtubeSearchUrl}/search?query=${exerciseDetailData.name}`, youtubeOptions)
setExerciseVideos(exerciseVideoData.contents)
const targetMuscleExercisesData = await fetchData(`${exerciseDbUrl}/exercises/target/${exerciseDetailData.target}`, exerciseOptions)
setTargetMuscleExercisesData(targetMuscleExercisesData)
const equipmentExercisesData = await fetchData(`${exerciseDbUrl}/exercises/equipment/${exerciseDetailData.equipment}`, exerciseOptions)
setEquipmentExercises(equipmentExercisesData)
}
setIsLoading(true)
setError(null)

try {
const exerciseDbUrl = 'https://exercisedb.p.rapidapi.com'
const youtubeSearchUrl = 'https://youtube-search-and-download.p.rapidapi.com'

// Fetch exercise details
const exerciseDetailData = await fetchData(`${exerciseDbUrl}/exercises/exercise/${id}`, exerciseOptions)
setExerciseDetails(exerciseDetailData)

// Fetch exercise videos
try {
const exerciseVideoData = await fetchData(`${youtubeSearchUrl}/search?query=${exerciseDetailData.name}`, youtubeOptions)
setExerciseVideos(exerciseVideoData.contents || [])
} catch (videoError) {
console.error('Error fetching exercise videos:', videoError)
// Continue with other fetches even if video fetch fails
setExerciseVideos([])
}

// Fetch target muscle exercises
try {
const targetMuscleExercisesData = await fetchData(`${exerciseDbUrl}/exercises/target/${exerciseDetailData.target}`, exerciseOptions)
setTargetMuscleExercisesData(targetMuscleExercisesData || [])
} catch (muscleError) {
console.error('Error fetching target muscle exercises:', muscleError)
setTargetMuscleExercisesData([])
}

// Fetch equipment exercises
try {
const equipmentExercisesData = await fetchData(`${exerciseDbUrl}/exercises/equipment/${exerciseDetailData.equipment}`, exerciseOptions)
setEquipmentExercises(equipmentExercisesData || [])
} catch (equipmentError) {
console.error('Error fetching equipment exercises:', equipmentError)
setEquipmentExercises([])
}
} catch (error) {
console.error('Error fetching exercise data:', error)
setError('Failed to load exercise details. Please try again later.')
} finally {
setIsLoading(false)
}
}

fetchExerciseData()
}, [id])

const handleRetry = () => {
window.location.reload()
}

if (isLoading) return <Loader />

if (error) {
return (
<Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'center', mt: 5, p: 3 }}>
<Alert severity="error" sx={{ mb: 2, width: '100%', maxWidth: '600px' }}>
{error}
</Alert>
<Typography variant="body1" sx={{ mb: 2 }}>
There was a problem loading the exercise details.
</Typography>
<button
onClick={handleRetry}
style={{
backgroundColor: '#FF2625',
color: '#fff',
padding: '10px 20px',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontWeight: 'bold'
}}
>
Try Again
</button>
</Box>
)
}

return (
<Box>
<Detail exerciseDetails={exerciseDetails}/>
<ExerciseVideos exerciseVideos={exerciseVideos} name={exerciseDetails.name}/>
<SimilarExercises targetMuscleExercises={targetMuscleExercises}equipmentExercises={equipmentExercises} />
<SimilarExercises targetMuscleExercises={targetMuscleExercises} equipmentExercises={equipmentExercises} />
</Box>
)
}

export default ExcerciseDetail
export default ExcerciseDetail
14 changes: 12 additions & 2 deletions src/utils/fetchData.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ export const youtubeOptions = {
};

export const fetchData = async(url, options) =>{
const response = await fetch(url,options)
const data = await response.json()
try {
const response = await fetch(url, options);

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const data = await response.json();
return data;
} catch (error) {
console.error(`Error fetching data from ${url}:`, error);
throw error; // Re-throw to allow component-level error handling
}
}