Skip to content

Commit

Permalink
Merge pull request #284 from bounswe/add-exercise-detail
Browse files Browse the repository at this point in the history
Add exercise detail
  • Loading branch information
MertCengiz authored Dec 14, 2024
2 parents 2aa7805 + 1ebd187 commit 2786245
Show file tree
Hide file tree
Showing 6 changed files with 380 additions and 7 deletions.
4 changes: 4 additions & 0 deletions mobile/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import ProgressTracker from './components/ProgressTracker';
import WorkoutDetails from './components/WorkoutDetails';
import JoinedWorkout from './components/JoinedWorkout';
import JoinedWeek from './components/JoinedWeek';
import JoinedExercise from './components/JoinedExercise';
import JoinedProgramDetail from './components/JoinedProgramDetail';

import { Provider as ReduxProvider } from 'react-redux';
import {
Expand Down Expand Up @@ -76,6 +78,8 @@ const App = () => {
<Stack.Screen name="WorkoutDetails" component={WorkoutDetails} />
<Stack.Screen name="JoinedWeek" component={JoinedWeek} />
<Stack.Screen name="JoinedWorkout" component={JoinedWorkout} />
<Stack.Screen name="JoinedExercise" component={JoinedExercise} />
<Stack.Screen name="JoinedProgramDetail" component={JoinedProgramDetail} />

</Stack.Navigator>
</NavigationContainer>
Expand Down
208 changes: 208 additions & 0 deletions mobile/components/JoinedExercise.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import React, { useState } from 'react';
import {
View,
Text,
TextInput,
StyleSheet,
TouchableOpacity,
ToastAndroid,
ScrollView,
} from 'react-native';

const ExerciseDetail = ({ route }) => {
const {programId,weekId,weekNumber,workoutId,workoutNumber,exerciseNumber,exerciseId,exercise,sets,repetitions} =route.params;

// Initialize state for the repetition inputs
const [repInputs, setRepInputs] = useState(Array(sets).fill(''));
const [isSubmitted, setIsSubmitted] = useState(false);

// Function to handle changes in input
const handleInputChange = (value, index) => {
var numbers = "0123456789";
if(value.length>0&&numbers.indexOf(value[value.length-1]) == -1 ) {
return;
}
//value = value.replace(/[^0-9]/g, '')
const updatedInputs = [...repInputs];
updatedInputs[index] = value;
setRepInputs(updatedInputs);
};

// Function to handle form submission
const handleSubmit = () => {
if(repInputs.some((rep)=>{return rep.length==0})){
ToastAndroid.show('Please fill all set fields!', ToastAndroid.SHORT);
return;
}
setIsSubmitted(true);
ToastAndroid.show('Successfully submitted!', ToastAndroid.SHORT);
};

return (
<ScrollView style={styles.container}>
<Text style={styles.title}>Session {exerciseNumber}: {exercise.name}</Text>

{/* Display GIF (Placeholder Image) */}
<View style={styles.gifContainer}>
<Text>[GIF Placeholder]</Text>
<Text style={styles.gifUrl}>{exercise.gifUrl}</Text>
</View>

{/* Details Section */}
<View style={styles.detailsContainer}>
<View style={styles.badgeContainer}>
<Text style={styles.badge}>Body Part: {exercise.bodyPart.toUpperCase()}</Text>
<Text style={styles.badge}>Target Muscle: {exercise.targetMuscle.toUpperCase()}</Text>
<Text style={styles.badge}>Equipment: {exercise.equipment.toUpperCase()}</Text>
</View>

<Text style={styles.sectionTitle}>Instructions:</Text>
<View style={styles.instructionsContainer}>
{exercise.instructions.map((instruction, idx) => (
<Text key={idx} style={styles.instruction}>
{instruction}
</Text>
))}
</View>

<Text style={styles.sectionTitle}>Secondary Muscles:</Text>
<View style={styles.secondaryMusclesContainer}>
{exercise.secondaryMuscles.map((muscle, idx) => (
<Text key={idx} style={styles.secondaryMuscleBadge}>
{muscle.toUpperCase()}
</Text>
))}
</View>
</View>

{/* Repetition Inputs */}
<Text style={styles.sectionTitle}>Enter Reps for Each Set:</Text>
<View style={styles.inputsContainer}>
{Array.from({ length: sets }).map((_, index) => (
<TextInput
key={index}
style={[styles.repInput, isSubmitted && styles.disabledInput]}
value={repInputs[index]}
onChangeText={(value) => handleInputChange(value, index)}
placeholder={`Set ${index + 1}`}
keyboardType="numeric"
maxLength = {2}
editable={!isSubmitted} // Disable inputs after submission
/>
))}
</View>

{/* Submit Button */}
<TouchableOpacity
style={[
styles.submitButton,
isSubmitted && styles.disabledButton,
]}
onPress={handleSubmit}
disabled={isSubmitted} // Disable button after submission
>
<Text style={styles.submitButtonText}>
{isSubmitted ? 'Submitted' : 'Submit Progress'}
</Text>
</TouchableOpacity>
</ScrollView>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
textAlign: 'center',
},
gifContainer: {
height: 200,
backgroundColor: '#f0f0f0',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 16,
borderRadius: 8,
},
gifUrl: {
fontSize: 12,
color: 'gray',
},
detailsContainer: {
marginBottom: 16,
},
badgeContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
marginBottom: 8,
},
badge: {
backgroundColor: '#e0f7fa',
color: '#00796b',
padding: 6,
borderRadius: 4,
margin: 4,
fontSize: 12,
},
sectionTitle: {
fontSize: 18,
fontWeight: 'bold',
marginTop: 16,
marginBottom: 8,
},
instructionsContainer: {
paddingHorizontal: 8,
},
instruction: {
fontSize: 14,
marginBottom: 4,
},
secondaryMusclesContainer: {
flexDirection: 'row',
flexWrap: 'wrap',
},
secondaryMuscleBadge: {
backgroundColor: '#fce4ec',
color: '#880e4f',
padding: 6,
borderRadius: 4,
margin: 4,
fontSize: 12,
},
inputsContainer: {
marginVertical: 16,
},
repInput: {
borderWidth: 1,
borderColor: '#ccc',
borderRadius: 4,
padding: 10,
fontSize: 16,
marginBottom: 8,
},
disabledInput: {
backgroundColor: '#f0f0f0',
color: '#aaa',
},
submitButton: {
backgroundColor: 'green',
padding: 16,
borderRadius: 8,
alignItems: 'center',
},
disabledButton: {
backgroundColor: '#aaa',
},
submitButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
},
});

export default ExerciseDetail;
164 changes: 164 additions & 0 deletions mobile/components/JoinedProgramDetail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import React,{useState} from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
FlatList,
ScrollView,
} from 'react-native';

const JoinedProgramDetail = ({ route }) => {
const {
trainerUsername,
title,
description,
programId,
weeks,
rating,
level,
date,
participants,
navigation
} = route.params;
const {expandedState,setExpandedState} = useState(0);
const renderWeek = ({ item, index }) => {
const workoutCount = item.workouts.length;
return (
<View style={styles.weekContainer}>
<Text style={styles.weekTitle}>Week {index + 1}</Text>
<Text style={styles.workoutCount}>{workoutCount} Workouts</Text>
<TouchableOpacity style={styles.startButton} onPress = {()=>{navigation.navigate("JoinedWeek",{programId,programTitle:title,weekId:item.id,weekNumber:item.weekNumber,workouts:item.workouts, navigation:navigation})}}>
<Text style={styles.startButtonText}>Start Workout</Text>
</TouchableOpacity>
<Text style={styles.completionText}>0%</Text>
</View>
);
};

return (
<ScrollView style={styles.container}>
<Text style={styles.title}>{title}</Text>
<View style={styles.detailsContainer}>
<Text style={styles.level}>Level: {level}</Text>
<Text style={styles.type}>Type: BODY_BUILDING</Text>
<Text style={styles.trainer}>Trainer: {trainerUsername}</Text>
<Text style={styles.date}>Created @ {date}</Text>
</View>
<Text style={styles.description}>{description}</Text>
<Text style={styles.rating}>Rating: {rating}/5 (0 ratings)</Text>

<FlatList
data={weeks}
renderItem={renderWeek}
keyExtractor={(item, index) => index.toString()}
/>

<TouchableOpacity style={styles.commitButton}>
<Text style={styles.commitButtonText}>Commit to Program</Text>
</TouchableOpacity>

<TouchableOpacity style={styles.detailButton} onPress = {()=>navigation.navigate("WorkoutDetails",{weeks,navigation})}>
<Text style={styles.detailButtonText}>Show Detailed Description</Text>
</TouchableOpacity>
</ScrollView>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: '#fff',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
textAlign: 'center',
},
detailsContainer: {
marginBottom: 16,
},
level: {
fontSize: 14,
color: 'orange',
},
type: {
fontSize: 14,
color: 'blue',
},
trainer: {
fontSize: 14,
color: 'red',
},
date: {
fontSize: 12,
color: 'gray',
},
description: {
fontSize: 16,
marginVertical: 8,
},
rating: {
fontSize: 16,
marginBottom: 16,
textAlign: 'center',
},
weekContainer: {
backgroundColor: '#f9f9f9',
padding: 16,
marginBottom: 8,
borderRadius: 8,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
weekTitle: {
fontSize: 16,
fontWeight: 'bold',
},
workoutCount: {
fontSize: 14,
color: 'gray',
},
startButton: {
backgroundColor: '#007bff',
paddingVertical: 8,
paddingHorizontal: 16,
borderRadius: 4,
},
startButtonText: {
color: '#fff',
fontSize: 14,
},
completionText: {
fontSize: 14,
color: 'green',
},
commitButton: {
backgroundColor: 'green',
padding: 16,
borderRadius: 8,
alignItems: 'center',
marginTop: 16,
},
commitButtonText: {
color: '#fff',
fontSize: 16,
fontWeight: 'bold',
},
detailButton: {
backgroundColor: 'gray',
padding: 16,
borderRadius: 8,
alignItems: 'center',
marginTop: 8,
},
detailButtonText: {
color: '#fff',
fontSize: 16,
},
});

export default JoinedProgramDetail;
Loading

0 comments on commit 2786245

Please sign in to comment.