Skip to content

Commit

Permalink
Merge pull request #364 from bounswe/add-rating-for-mobile
Browse files Browse the repository at this point in the history
Add rating for mobile
  • Loading branch information
MertCengiz authored Dec 16, 2024
2 parents b9e1d82 + ca80d96 commit 7aa9758
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 20 deletions.
23 changes: 22 additions & 1 deletion mobile/components/JoinedProgramCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,33 @@ import { useSelector } from 'react-redux';
import { userName, userSessionToken } from '../user.js';
import { useQuery } from "@tanstack/react-query"
import apiInstance from '../Api';
const JoinedProgramCard = ({ trainerUsername, trackingId, title, description, programId, weeks, rating, level, joined, date, participants, navigation }) => {
const JoinedProgramCard = ({ trainerUsername, trackingId, title, description, programId, weeks, level, joined, date, participants, navigation }) => {

const sessionToken = useSelector(userSessionToken)
const [completion,setCompletion] = useState({});
const [rating,setRating] = useState(0);
const username = useSelector(userName)
console.log(username);
const {
data: ratingData,
isFetching: ratingIsFetching,
isLoading: ratingIsLoading,
} = useQuery({
queryKey: [`training-program-rating-${programId}`],
queryFn: async () => {
const response = await apiInstance().get(`api/training-programs/${programId}`)

return response.data
},
refetchOnWindowFocus:true,
refetchInterval:60000,
})

useEffect(() => {
if (ratingData && !ratingIsFetching) {
setRating(ratingData.rating)
}
}, [ratingData, ratingIsFetching])
const {
data: completionData,
isFetching: programsIsFetching,
Expand Down
161 changes: 142 additions & 19 deletions mobile/components/JoinedProgramDetail.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React,{useState, useEffect} from 'react';
import React, { useState } from 'react';
import {
View,
Text,
Expand All @@ -7,10 +7,17 @@ import {
FlatList,
ScrollView,
} from 'react-native';
import Slider from '@react-native-community/slider';
import { useSelector } from 'react-redux';
import { userSessionToken } from '../user.js';
import { useQuery } from "@tanstack/react-query"
import { userName,userSessionToken } from '../user.js';
import { useQuery } from "@tanstack/react-query";
import apiInstance from '../Api';
import Toast from 'react-native-toast-message'

//POST /api/training-programs/{trainingProgramId}/rate?userId={userId}&rating={rating}




const JoinedProgramDetail = ({ route }) => {
const {
Expand All @@ -25,30 +32,100 @@ const JoinedProgramDetail = ({ route }) => {
level,
date,
participants,
navigation
navigation,
} = route.params;
console.log(trackingId);
const {expandedState,setExpandedState} = useState(0);



const [userRating, setUserRating] = useState(rating || 0);
const [isRated, setIsRated] = useState(false);
const sessionToken = useSelector(userSessionToken);
console.log("Completion response for detail is: "+completion)
for (const [key, value] of Object.entries(completion)) {
console.log(`${key}: ${value}`);
}
const renderWeek = ({ item, index}) => {
const username = useSelector(userName);


const handleRating = async (rt) => {
setUserRating(rt);
try {
console.log("Rating is: "+rt);
const response = await apiInstance(sessionToken).post(`api/training-programs/${programId}/rate?rating=${rt}`, {

});
console.log("Rating response is:");
console.log(response);

if (Math.floor(response.status/100) == 2) {
Toast.show({
type: 'success',
position: 'bottom',
text1: 'Program Rated',
text2: 'Your rating has been sent successfully.',
visibilityTime: 3000,
autoHide: true,
topOffset: 30,
bottomOffset: 40
});
}
} catch (e) {
//console.log(e)
Toast.show({
type: 'error',
position: 'bottom',
text1: 'Rating Error',
text2: 'Network error.',
visibilityTime: 3000,
autoHide: true,
topOffset: 30,
bottomOffset: 40
}); }
};

const renderWeek = ({ item, index }) => {
const workoutCount = item.workouts.length;
console.log("Completion is: "+completion["10"])
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, trackingId, programTitle:title,weekId:item.id,weekNumber:item.weekNumber,workouts:item.workouts, navigation:navigation})}}>
<TouchableOpacity
style={styles.startButton}
onPress={() => {
navigation.navigate("JoinedWeek", {
programId,
trackingId,
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}>%{Object.keys(completion).length>0?completion[`${item.id}`]:0}</Text>
<Text style={styles.completionText}>
%{Object.keys(completion).length > 0 ? completion[`${item.id}`] : 0}
</Text>
</View>
);
};

const renderStars = () => {
const stars = [];
for (let i = 1; i <= 5; i++) {
stars.push(
<TouchableOpacity
key={i}
onPress={() => {
handleRating(i);
setIsRated(true);
}}
>
<Text style={i <= userRating ? styles.filledStar : styles.emptyStar}></Text>
</TouchableOpacity>
);
}
return stars;
};

return (
<ScrollView style={styles.container}>
<Text style={styles.title}>{title}</Text>
Expand All @@ -59,7 +136,23 @@ const JoinedProgramDetail = ({ route }) => {
<Text style={styles.date}>Created @ {date}</Text>
</View>
<Text style={styles.description}>{description}</Text>
<Text style={styles.rating}>Rating: {rating}/5 (0 ratings)</Text>

<View style={styles.ratingContainer}>
<Text style={styles.ratingLabel}>{isRated ? "Your Rating" : "Average Rating"}</Text>
<View style={styles.starsContainer}>{renderStars()}</View>
<Slider
style={styles.slider}
minimumValue={0}
maximumValue={5}
step={1}
value={userRating}
onValueChange={(value) => {
handleRating(value);
setIsRated(true);
}}
/>
<Text style={styles.sliderValue}>{userRating} / 5</Text>
</View>

<FlatList
data={weeks}
Expand All @@ -71,7 +164,12 @@ const JoinedProgramDetail = ({ route }) => {
<Text style={styles.commitButtonText}>Commit to Program</Text>
</TouchableOpacity>

<TouchableOpacity style={styles.detailButton} onPress = {()=>navigation.navigate("WorkoutDetails",{weeks,navigation})}>
<TouchableOpacity
style={styles.detailButton}
onPress={() =>
navigation.navigate("WorkoutDetails", { weeks, navigation })
}
>
<Text style={styles.detailButtonText}>Show Detailed Description</Text>
</TouchableOpacity>
</ScrollView>
Expand Down Expand Up @@ -113,10 +211,35 @@ const styles = StyleSheet.create({
fontSize: 16,
marginVertical: 8,
},
rating: {
ratingContainer: {
alignItems: 'center',
marginVertical: 16,
},
ratingLabel: {
fontSize: 16,
marginBottom: 16,
textAlign: 'center',
marginBottom: 8,
},
starsContainer: {
flexDirection: 'row',
marginBottom: 8,
},
filledStar: {
fontSize: 24,
color: 'gold',
marginHorizontal: 4,
},
emptyStar: {
fontSize: 24,
color: 'gray',
marginHorizontal: 4,
},
slider: {
width: '80%',
height: 40,
},
sliderValue: {
fontSize: 16,
marginTop: 8,
},
weekContainer: {
backgroundColor: '#f9f9f9',
Expand Down
7 changes: 7 additions & 0 deletions mobile/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
},
"dependencies": {
"@react-native-async-storage/async-storage": "^2.1.0",
"@react-native-community/slider": "^4.5.5",
"@react-native-picker/picker": "^2.9.0",
"@react-navigation/native": "^6.1.18",
"@react-navigation/stack": "^6.4.1",
Expand Down

0 comments on commit 7aa9758

Please sign in to comment.