Commit de015c32 authored by Isura Eranda's avatar Isura Eranda

new

parent 94ea193e
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -19,11 +19,14 @@ ...@@ -19,11 +19,14 @@
"@react-navigation/native": "^6.1.17", "@react-navigation/native": "^6.1.17",
"@react-navigation/stack": "^6.3.29", "@react-navigation/stack": "^6.3.29",
"axios": "^1.6.8", "axios": "^1.6.8",
"cloudinary": "^2.2.0",
"cloudinary-react-native": "^1.0.0",
"formik": "^2.4.6", "formik": "^2.4.6",
"metro-react-native-babel-preset": "^0.77.0", "metro-react-native-babel-preset": "^0.77.0",
"moment": "^2.30.1", "moment": "^2.30.1",
"react": "18.2.0", "react": "18.2.0",
"react-native": "0.73.6", "react-native": "0.73.6",
"react-native-chart-kit": "^6.12.0",
"react-native-circular-progress": "^1.4.0", "react-native-circular-progress": "^1.4.0",
"react-native-circular-progress-indicator": "^4.4.2", "react-native-circular-progress-indicator": "^4.4.2",
"react-native-gesture-handler": "^2.16.2", "react-native-gesture-handler": "^2.16.2",
...@@ -41,7 +44,6 @@ ...@@ -41,7 +44,6 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0", "@babel/core": "^7.20.0",
"react-native-image-picker": "^7.1.1",
"@babel/preset-env": "^7.20.0", "@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0", "@babel/runtime": "^7.20.0",
"@react-native/babel-preset": "0.73.21", "@react-native/babel-preset": "0.73.21",
...@@ -54,6 +56,7 @@ ...@@ -54,6 +56,7 @@
"eslint": "^8.19.0", "eslint": "^8.19.0",
"jest": "^29.6.3", "jest": "^29.6.3",
"prettier": "2.8.8", "prettier": "2.8.8",
"react-native-image-picker": "^7.1.1",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"typescript": "5.0.4" "typescript": "5.0.4"
}, },
......
import React, { useState, useRef, useEffect } from 'react'; import React, { useState, useRef, useEffect, useCallback } from 'react';
import { StyleSheet, Text, View, ActivityIndicator, TouchableOpacity, ToastAndroid, Dimensions, SafeAreaView, ScrollView,FlatList } from 'react-native'; import { StyleSheet, Text, View, ActivityIndicator, TouchableOpacity, ToastAndroid, Dimensions, SafeAreaView, ScrollView, FlatList, Modal } from 'react-native';
import LinearGradient from 'react-native-linear-gradient'; import LinearGradient from 'react-native-linear-gradient';
import Video from 'react-native-video'; import Video from 'react-native-video';
import { Camera, useCameraDevice, CameraPermissionStatus } from 'react-native-vision-camera'; import { Camera, useCameraDevice, CameraPermissionStatus } from 'react-native-vision-camera';
...@@ -7,9 +7,16 @@ import CircleProgressBar from '../../../components/CircleProgressBar'; ...@@ -7,9 +7,16 @@ import CircleProgressBar from '../../../components/CircleProgressBar';
import { COLORS, ROUTES } from '../../../constants'; import { COLORS, ROUTES } from '../../../constants';
import Dot from '../../../assets/icons/dot.svg'; import Dot from '../../../assets/icons/dot.svg';
const { width } = Dimensions.get('window'); const { width } = Dimensions.get('window');
const cameraWidth = width * 0.8; // Example: 80% of the screen width let cameraWidth = width * 0.8; // Example: 80% of the screen width
const cameraHeight = cameraWidth * (16 / 9); // Maintain 16:9 aspect ratio let cameraHeight = cameraWidth * (16 / 9); // Maintain 16:9 aspect ratio
const { height: screenHeight } = Dimensions.get('window'); const { height: screenHeight } = Dimensions.get('window');
// import cloudinary from './cloudinary'; // Adjust the path as necessary
import axios from 'axios';
// import { CldVideo } from 'cloudinary-react-native';
// import { Cloudinary } from "@cloudinary/url-gen";
// import { upload } from 'cloudinary-react-native';
import { useFocusEffect } from '@react-navigation/native';
const ExerciseView = (props) => { const ExerciseView = (props) => {
let { route, navigation } = props; let { route, navigation } = props;
...@@ -22,8 +29,29 @@ const ExerciseView = (props) => { ...@@ -22,8 +29,29 @@ const ExerciseView = (props) => {
const [startCountDown, setStartCountDown] = useState(false); const [startCountDown, setStartCountDown] = useState(false);
const [isRecording, setIsRecording] = useState(false); const [isRecording, setIsRecording] = useState(false);
const [videoSource, setVideoSource] = useState(''); const [videoSource, setVideoSource] = useState('');
const [photo, setPhoto] = useState('');
const [completeStatus, setCompleteStatus] = useState(false); const [completeStatus, setCompleteStatus] = useState(false);
const [refreshing, setRefreshing] = useState(false);
const [modalVisible, setModalVisible] = useState(true);
const [newCameraHeight, setNewCameraHeight] = useState('');
const [newCameraWidth, setNewCameraWidth] = useState('');
const device = useCameraDevice('front') const device = useCameraDevice('front')
const [dimensions, setDimensions] = useState({ width: Dimensions.get('window').width, height: Dimensions.get('window').height });
// useEffect(() => {
// const onChange = ({ window }) => {
// setDimensions({ width: window.width * (0.7), height: window.height });
// };
// Dimensions.addEventListener('change', onChange);
// return () => {
// Dimensions.removeEventListener('change', onChange);
// };
// }, []);
const handleLoad = () => { const handleLoad = () => {
setLoading(false); setLoading(false);
...@@ -35,6 +63,7 @@ const ExerciseView = (props) => { ...@@ -35,6 +63,7 @@ const ExerciseView = (props) => {
const handlePlay = () => { const handlePlay = () => {
setVideoPaused(false); setVideoPaused(false);
startRecording()
}; };
const handlePause = () => { const handlePause = () => {
...@@ -44,30 +73,32 @@ const ExerciseView = (props) => { ...@@ -44,30 +73,32 @@ const ExerciseView = (props) => {
const moveToNext = () => { const moveToNext = () => {
navigation.navigate(ROUTES.EXERCISE_MAIN_MENU) navigation.navigate(ROUTES.EXERCISE_MAIN_MENU)
ToastAndroid.show('Navigation successfully !', ToastAndroid.SHORT); ToastAndroid.show('Navigation successfully !', ToastAndroid.SHORT);
}; };
const handleStop = () => { const handleStop = async () => {
setRemainingTime(0); setRemainingTime(0);
setCompleteStatus(true) setCompleteStatus(true);
navigation.navigate(ROUTES.EXERCISE_MAIN_MENU) await stopRecording();
ToastAndroid.show('Navigation successfully !', ToastAndroid.SHORT);
}; };
const handleVideoEnd = () => { const handleVideoEnd = () => {
setVideoPaused(true); setVideoPaused(true);
// setStartCountDown(true); // setStartCountDown(true);
setRemainingTime(data.duration); // Reset remaining time setRemainingTime(data.duration); // Reset remaining time
}; };
const startRecording = async () => { const startRecording = async () => {
if (cameraRef.current && !isRecording) { if (cameraRef.current && !isRecording) {
setIsRecording(true); setIsRecording(true);
const video = await cameraRef.current.startRecording({ const video = await cameraRef.current.startRecording({
onRecordingFinished: (video) => { onRecordingFinished: async (video) => {
setVideoSource(video.path); setVideoSource(video.path);
setIsRecording(false); setIsRecording(false);
console.log(video.path); console.log(video);
}, },
onRecordingError: (error) => { onRecordingError: (error) => {
console.error(`Recording Error: ${error.message}`); console.error(`Recording Error: ${error.message}`);
...@@ -84,6 +115,24 @@ const ExerciseView = (props) => { ...@@ -84,6 +115,24 @@ const ExerciseView = (props) => {
} }
}; };
const onRefresh = () => {
setRefreshing(true);
// Add any data fetching or reloading logic here
setRemainingTime(data.duration * 2);
setLoading(true);
setVideoPaused(true);
setCompleteStatus(false);
setVideoSource('');
setRefreshing(false);
console.log("width", cameraWidth)
};
useFocusEffect(
useCallback(() => {
onRefresh();
}, [])
);
useEffect(() => { useEffect(() => {
// Initialize remainingTime when component mounts // Initialize remainingTime when component mounts
setRemainingTime(data.duration * 2); setRemainingTime(data.duration * 2);
...@@ -116,6 +165,33 @@ const ExerciseView = (props) => { ...@@ -116,6 +165,33 @@ const ExerciseView = (props) => {
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<ScrollView style={{ height: screenHeight, paddingBottom: 30, marginBottom: 30 }}> <ScrollView style={{ height: screenHeight, paddingBottom: 30, marginBottom: 30 }}>
<Text style={styles.title}>Exercise Details</Text> <Text style={styles.title}>Exercise Details</Text>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<View style={styles.textView}>
<Dot width={16} height={16} color={COLORS.primary} style={styles.dotIcon} />
<Text>Recording video on the exercise to collect the progress. 😊</Text>
</View>
<View style={styles.textView}>
<Dot width={16} height={16} color={COLORS.primary} style={styles.dotIcon} />
<Text>Make sure to place phone correctly to preview😊</Text>
</View>
<View style={styles.closeDiv}>
<TouchableOpacity onPress={() => { setModalVisible(false); }}>
<Text style={styles.closeButton}>Close</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<View style={styles.videoContainer}> <View style={styles.videoContainer}>
<Video <Video
...@@ -138,13 +214,13 @@ const ExerciseView = (props) => { ...@@ -138,13 +214,13 @@ const ExerciseView = (props) => {
<Text>{remainingTime} seconds</Text> <Text>{remainingTime} seconds</Text>
</View> </View>
</View> </View>
<View style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'coloum', paddingHorizontal: 0}}> <View style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', flexDirection: 'coloum', paddingHorizontal: 0 }}>
{remainingTime > 0 && {remainingTime > 0 &&
<View style={styles.buttonsContainer}> <View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}> <TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}>
<Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text> <Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style={styles.buttonRed} onPress={moveToNext}> <TouchableOpacity style={styles.buttonRed} onPress={handleStop}>
<Text style={styles.buttonText}>Stop</Text> <Text style={styles.buttonText}>Stop</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
...@@ -156,7 +232,6 @@ const ExerciseView = (props) => { ...@@ -156,7 +232,6 @@ const ExerciseView = (props) => {
style={styles.linearGradient} style={styles.linearGradient}
start={{ y: 0.0, x: 0.0 }} start={{ y: 0.0, x: 0.0 }}
end={{ y: 1.0, x: 0.0 }}> end={{ y: 1.0, x: 0.0 }}>
{/******************** LOGIN BUTTON *********************/}
<TouchableOpacity activeOpacity={0.7} style={styles.loginBtn} onPress={moveToNext}> <TouchableOpacity activeOpacity={0.7} style={styles.loginBtn} onPress={moveToNext}>
<Text style={styles.loginText}>Move To Next</Text> <Text style={styles.loginText}>Move To Next</Text>
</TouchableOpacity> </TouchableOpacity>
...@@ -173,9 +248,7 @@ const ExerciseView = (props) => { ...@@ -173,9 +248,7 @@ const ExerciseView = (props) => {
isActive={true} isActive={true}
video={true} video={true}
audio={true} audio={true}
ratio="16:9"
/> />
</View> </View>
</ScrollView> </ScrollView>
</SafeAreaView> </SafeAreaView>
...@@ -297,7 +370,7 @@ const styles = StyleSheet.create({ ...@@ -297,7 +370,7 @@ const styles = StyleSheet.create({
}, },
cameraContainer: { cameraContainer: {
display: 'flex', display: 'flex',
width: width, width: 380,
marginTop: 5, marginTop: 5,
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
...@@ -305,8 +378,6 @@ const styles = StyleSheet.create({ ...@@ -305,8 +378,6 @@ const styles = StyleSheet.create({
camera: { camera: {
width: cameraWidth, width: cameraWidth,
height: cameraHeight, height: cameraHeight,
justifyContent: 'flex-end',
alignItems: 'center',
}, },
// Login Btn Styles // Login Btn Styles
loginBtnWrapper: { loginBtnWrapper: {
...@@ -345,538 +416,46 @@ const styles = StyleSheet.create({ ...@@ -345,538 +416,46 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
flexWrap: 'wrap', flexWrap: 'wrap',
}, },
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
justifyContent: "center",
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
alignContent: "flex-start",
alignItems: "flex-start"
},
modalText: {
marginBottom: 15,
textAlign: "center"
},
closeButton: {
marginTop: 10,
color: COLORS.primary,
textAlign: 'center',
fontSize: 18,
fontWeight: 'bold',
},
textView: {
display: "flex",
flexDirection: "row",
marginTop: 5
},
closeDiv: {
width: "100%",
display: "flex",
alignItems: "flex-end",
alignContent: "flex-end",
},
}); });
export default ExerciseView; export default ExerciseView;
\ No newline at end of file
// import React, { useState, useRef, useEffect } from 'react';
// import { StyleSheet, Text, View, ActivityIndicator, TouchableOpacity } from 'react-native';
// import Video from 'react-native-video';
// import CircleProgressBar from '../../../components/CircleProgressBar';
// import { COLORS, ROUTES } from '../../../constants';
// import Dot from '../../../assets/icons/dot.svg';
// const ExerciseView = (props) => {
// const { route } = props;
// const { data } = route.params; // Assuming you pass videoUrl as a route parameter
// const videoRef = useRef(null);
// const [loading, setLoading] = useState(true);
// const [videoPaused, setVideoPaused] = useState(true);
// const [remainingTime, setRemainingTime] = useState(data.duration);
// const [startCountDown, setStartCountDown] = useState(false);
// const handleLoad = () => {
// setLoading(false);
// };
// const handleBuffer = () => {
// setLoading(true);
// };
// const handlePlay = () => {
// setVideoPaused(false);
// };
// const handlePause = () => {
// setVideoPaused(true);
// };
// const handleVideoEnd = () => {
// setVideoPaused(true);
// setStartCountDown(true);
// setRemainingTime(data.duration); // Reset remaining time
// };
// useEffect(() => {
// if (remainingTime > 0 && startCountDown) {
// const interval = setInterval(() => {
// setRemainingTime((prevTime) => prevTime - 1);
// }, 1000);
// return () => clearInterval(interval);
// }
// }, [remainingTime, startCountDown]);
// return (
// <View style={styles.container}>
// <Text style={styles.title}>Exercise Session</Text>
// <View style={styles.videoContainer}>
// <Video
// ref={videoRef}
// source={{ uri: data.exercise_video_url }}
// style={styles.video}
// controls={true}
// paused={videoPaused}
// resizeMode="contain"
// onLoad={handleLoad}
// onBuffer={handleBuffer}
// onEnd={handleVideoEnd}
// />
// {loading && <ActivityIndicator style={styles.loader} size="large" color="#0000ff" />}
// <View style={styles.buttonsContainer}>
// <TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}>
// <Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text>
// </TouchableOpacity>
// <TouchableOpacity style={styles.button} onPress={handlePause}>
// <Text style={styles.buttonText}>Stop</Text>
// </TouchableOpacity>
// </View>
// <View style={styles.progressMainView}>
// <CircleProgressBar percentage={(remainingTime / data.duration) * 100} />
// <View style={styles.progressSecondView}>
// <Text>Remaining</Text>
// <Text>{remainingTime} seconds</Text>
// </View>
// </View>
// <View style={styles.stepsContainer}>
// <Text style={styles.stepsTitle}>Steps:</Text>
// {data.exer_steps.map((step, index) => (
// <View key={index} style={styles.stepContainer}>
// {index !== 0 && <View style={styles.line} />}
// <Dot width={16} height={16} color={COLORS.primary} style={styles.dotIcon} />
// {/* {index < data.exer_steps.length - 1 && <View style={styles.line}></View>} */}
// <Text style={styles.stepItem}>{step.step}</Text>
// </View>
// ))}
// </View>
// </View>
// </View>
// );
// };
// const styles = StyleSheet.create({
// container: {
// flex: 1,
// backgroundColor: '#fff',
// alignItems: 'center',
// },
// title: {
// fontSize: 20,
// fontWeight: 'bold',
// marginBottom: 20,
// textAlign: 'center',
// },
// videoContainer: {
// width: '100%',
// aspectRatio: 16 / 9,
// justifyContent: 'center',
// alignItems: 'center',
// marginTop: 40,
// position: 'absolute',
// top: '25%',
// },
// video: {
// width: '100%',
// height: '100%',
// },
// loader: {
// position: 'absolute',
// top: '50%',
// left: '50%',
// transform: [{ translateX: -25 }, { translateY: -25 }],
// },
// buttonsContainer: {
// flexDirection: 'row',
// marginTop: 10,
// paddingTop: 10,
// paddingBottom: 10,
// },
// button: {
// backgroundColor: '#2196F3',
// padding: 10,
// borderRadius: 50,
// marginHorizontal: 5,
// },
// buttonText: {
// color: 'white',
// fontWeight: 'bold',
// },
// progressMainView: {
// display: 'flex',
// flexDirection: 'row',
// justifyContent: 'space-between',
// shadowColor: '#000',
// shadowOffset: {
// width: 2,
// height: 2,
// },
// shadowOpacity: 0.25,
// shadowRadius: 3.84,
// elevation: 5,
// backgroundColor: COLORS.white,
// marginHorizontal: 20,
// borderRadius: 15,
// marginTop: 10,
// paddingVertical: 10,
// },
// progressSecondView: {
// paddingLeft: 10,
// paddingRight: 20,
// paddingTop: 20,
// },
// stepsContainer: {
// marginTop: 20,
// paddingHorizontal: 20,
// width: "100%"
// },
// stepsTitle: {
// fontSize: 18,
// fontWeight: 'bold',
// marginBottom: 10,
// },
// stepContainer: {
// flexDirection: 'row',
// alignItems: 'center',
// marginBottom: 5,
// },
// dotIcon: {
// marginRight: 5,
// },
// // line: {
// // flex: 1,
// // height: 1,
// // backgroundColor: COLORS.primary, // Change to your desired color
// // marginLeft: 8,
// // marginRight: 8,
// // },
// stepItem: {
// flex: 1,
// },
// line: {
// width: 1,
// height: 20,
// backgroundColor: 'black',
// marginHorizontal: 5,
// },
// });
// export default ExerciseView;
// import React, { useState, useRef, useEffect} from 'react';
// import { StyleSheet, Text, View, ActivityIndicator,TouchableOpacity } from 'react-native';
// import Video from 'react-native-video';
// import CircleProgressBar from '../../../components/CircleProgressBar';
// import { COLORS, ROUTES } from '../../../constants';
// const ExerciseView = (props) => {
// const { route } = props;
// const { data } = route.params; // Assuming you pass videoUrl as a route parameter
// const videoRef = useRef(null);
// const [loading, setLoading] = useState(true);
// const [videoPaused, setVideoPaused] = useState(true);
// const [remainingTime, setRemainingTime] = useState(data.duration);
// const [startCountDown, setStartCountDown] = useState(false);
// const handleLoad = () => {
// setLoading(false);
// };
// const handleBuffer = () => {
// setLoading(true);
// };
// const handlePlay = () => {
// setVideoPaused(false);
// };
// const handlePause = () => {
// setVideoPaused(true);
// };
// const handleVideoEnd = () => {
// console.log("vide0 end")
// setVideoPaused(true);
// setStartCountDown(true)
// setRemainingTime(data.duration); // Reset remaining time
// }
// useEffect(() => {
// if (remainingTime > 0 && startCountDown == true) {
// const interval = setInterval(() => {
// setRemainingTime(prevTime => prevTime - 1);
// }, 1000);
// return () => clearInterval(interval);
// }
// }, [remainingTime, startCountDown]);
// return (
// <View style={styles.container}>
// <Text style={styles.title}>Exercise Details</Text>
// <View style={styles.videoContainer}>
// <Video
// ref={videoRef}
// source={{ uri: data.exercise_video_url }}
// style={styles.video}
// controls={true}
// paused={videoPaused}
// resizeMode="contain"
// onLoad={handleLoad}
// onBuffer={handleBuffer}
// onEnd={handleVideoEnd}
// />
// {loading && <ActivityIndicator style={styles.loader} size="large" color="#0000ff" />}
// <View style={styles.buttonsContainer}>
// <TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}>
// <Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text>
// </TouchableOpacity>
// <TouchableOpacity style={styles.button} onPress={handlePause}>
// <Text style={styles.buttonText}>Stop</Text>
// </TouchableOpacity>
// </View>
// <View style={styles.progressMainView}>
// <CircleProgressBar percentage={(remainingTime / data.duration) * 100} />
// <View style={styles.progressSecondView}>
// <Text>Remaining</Text>
// <Text>{remainingTime} seconds</Text>
// </View>
// </View>
// <View style={styles.stepsContainer}>
// <Text style={styles.stepsTitle}>Steps:</Text>
// {data.exer_steps.map((step, index) => (
// <Text key={index} style={styles.stepItem}>{step.step}</Text>
// ))}
// </View>
// </View>
// </View>
// );
// }
// const styles = StyleSheet.create({
// container: {
// flex: 1,
// backgroundColor: '#fff',
// alignItems: 'center',
// },
// title: {
// fontSize: 20,
// fontWeight: 'bold',
// marginBottom: 20,
// textAlign: 'center',
// },
// videoContainer: {
// width: '100%',
// aspectRatio: 16 / 9, // You can adjust this aspect ratio as needed
// justifyContent: 'center',
// alignItems: 'center',
// marginTop: 50,
// position: 'absolute',
// top: '25%',
// },
// video: {
// width: '100%',
// height: '100%',
// },
// loader: {
// position: 'absolute',
// top: '50%',
// left: '50%',
// transform: [{ translateX: -25 }, { translateY: -25 }], // Adjust according to your loader size
// },
// buttonsContainer: {
// flexDirection: 'row',
// marginTop: 10,
// paddingTop: 10,
// paddingBottom: 10
// },
// button: {
// backgroundColor: '#2196F3',
// padding: 10,
// borderRadius: 50, // This will make the button round
// marginHorizontal: 5,
// },
// buttonText: {
// color: 'white',
// fontWeight: 'bold',
// },
// progressMainView: {
// display: 'flex',
// flexDirection: "row",
// justifyContent: 'space-between',
// shadowColor: '#000',
// shadowOffset: {
// width: 2,
// height: 2,
// },
// shadowOpacity: 0.25,
// shadowRadius: 3.84,
// elevation: 5,
// backgroundColor: COLORS.white,
// marginHorizontal: 20,
// borderRadius: 15,
// marginTop: 10,
// paddingVertical: 10
// },
// progressSecondView: {
// paddingLeft: 10,
// paddingRight: 20,
// paddingTop: 20
// }
// });
// export default ExerciseView;
// import React, { useState, useRef, useEffect } from 'react';
// import { StyleSheet, Text, View, ActivityIndicator, TouchableOpacity } from 'react-native';
// import Video from 'react-native-video';
// import CircleProgressBar from '../../../components/CircleProgressBar';
// const ExerciseView = (props) => {
// const { route } = props;
// const { data } = route.params; // Assuming you pass videoUrl as a route parameter
// const videoRef = useRef(null);
// const [loading, setLoading] = useState(true);
// const [videoPaused, setVideoPaused] = useState(true);
// const [remainingTime, setRemainingTime] = useState(data.duration);
// const [startCountDown, setStartCountDown] = useState(false);
// const handleLoad = () => {
// setLoading(false);
// };
// const handleBuffer = () => {
// setLoading(true);
// };
// const handlePlay = () => {
// setVideoPaused(false);
// };
// const handlePause = () => {
// setVideoPaused(true);
// };
// const handlePlaybackStatusUpdate = (status) => {
// if (status.isPlaying && !status.isBuffering && remainingTime > 0) {
// setRemainingTime((prev) => prev - 1);
// }
// };
// const handleVideoEnd = () => {
// console.log("vide0 end")
// setVideoPaused(true);
// setStartCountDown(true)
// setRemainingTime(data.duration); // Reset remaining time
// }
// useEffect(() => {
// if (remainingTime > 0 && startCountDown == true) {
// const interval = setInterval(() => {
// setRemainingTime(prevTime => prevTime - 1);
// }, 1000);
// return () => clearInterval(interval);
// }
// }, [remainingTime, startCountDown]);
// return (
// <View style={styles.container}>
// <Text style={styles.title}>Exercise Details</Text>
// <View style={styles.videoContainer}>
// <Video
// ref={videoRef}
// source={{ uri: data.exercise_video_url }}
// style={styles.video}
// controls={false}
// paused={videoPaused}
// resizeMode="contain" // This ensures the video fits within its container
// onLoad={handleLoad}
// onBuffer={handleBuffer}
// onPlaybackStatusUpdate={handlePlaybackStatusUpdate} // Add this event handler to update remaining time
// onEnd={handleVideoEnd} // Add this event handler to restart countdown after video ends
// />
// {loading && <ActivityIndicator style={styles.loader} size="large" color="#0000ff" />}
// <CircleProgressBar percentage={(remainingTime / data.duration) * 100} />
// <Text>Remaining Time: {remainingTime} seconds</Text>
// <View style={styles.buttonsContainer}>
// <TouchableOpacity style={styles.button} onPress={videoPaused ? handlePlay : handlePause}>
// <Text style={styles.buttonText}>{videoPaused ? 'Play' : 'Pause'}</Text>
// </TouchableOpacity>
// <TouchableOpacity style={styles.button} onPress={handlePause}>
// <Text style={styles.buttonText}>Stop</Text>
// </TouchableOpacity>
// </View>
// </View>
// </View>
// );
// }
// const styles = StyleSheet.create({
// container: {
// flex: 1,
// backgroundColor: '#fff',
// alignItems: 'center',
// },
// title: {
// fontSize: 20,
// fontWeight: 'bold',
// marginBottom: 20,
// textAlign: 'center',
// },
// videoContainer: {
// width: '100%',
// aspectRatio: 16 / 9, // You can adjust this aspect ratio as needed
// justifyContent: 'center',
// alignItems: 'center',
// position: 'relative', // Ensure CircleProgressBar and Text are positioned relative to video
// },
// video: {
// width: '100%',
// height: '100%',
// },
// loader: {
// position: 'absolute',
// top: '50%',
// left: '50%',
// transform: [{ translateX: -25 }, { translateY: -25 }], // Adjust according to your loader size
// },
// buttonsContainer: {
// flexDirection: 'row',
// marginTop: 10,
// },
// button: {
// backgroundColor: '#2196F3',
// padding: 10,
// borderRadius: 5,
// marginHorizontal: 5,
// },
// buttonText: {
// color: 'white',
// fontWeight: 'bold',
// },
// });
// export default ExerciseView;
{/* <FlatList
data={[...data.exer_steps, { isCamera: true }]} // Adding a placeholder for the camera view
renderItem={({ item, index }) => (
item.isCamera ? (
<View style={styles.cameraContainer}>
<Camera
ref={cameraRef}
style={styles.camera}
device={device}
isActive={true}
video={true}
audio={true}
ratio="16:9"
/>
</View>
) : (
<View style={{ marginHorizontal: 5 }}>
{data.exer_steps.map((step, index) => (
<View key={index} style={styles.stepContainer}>
<Dot width={16} height={16} color={COLORS.primary} style={styles.dotIcon} />
<Text style={styles.stepItem}>{step.step}</Text>
</View>
))}
</View>
)
)}
keyExtractor={(item, index) => index.toString()}
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.horizontalFlatList}
/> */}
\ No newline at end of file
...@@ -9,20 +9,60 @@ import { ...@@ -9,20 +9,60 @@ import {
Image, Image,
View, View,
ScrollView, ScrollView,
Button Button,
Dimensions
} from 'react-native'; } from 'react-native';
import Logo from '../../../assets/icons/progress.svg'; import Logo from '../../../assets/icons/progress.svg';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
import {
ProgressChart
} from "react-native-chart-kit";
// each value represents a goal ring in Progress chart
const data = {
labels: ["Session 1", "Session 2", "Session 3"], // optional
data: [0.4, 0.0, 0.0]
};
const { width } = Dimensions.get('window');
const ExercisesProgress = (props) => { const ExercisesProgress = (props) => {
const chartConfig={
backgroundColor: "#e26a00",
backgroundGradientFrom: "#fb8c00",
backgroundGradientTo: "#ffa726",
decimalPlaces: 2, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
labelColor: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 16
},
propsForDots: {
r: "6",
strokeWidth: "2",
stroke: "#ffa726"
},
}
return ( return (
<SafeAreaView style={styles.container}> <SafeAreaView style={styles.container}>
<View style={styles.secondContainer} > <View style={styles.secondContainer} >
<Text style={styles.topTextMain}>ExercisesProgress</Text> <Text style={styles.topTextMain}>ExercisesProgress</Text>
</View> </View>
<View style={styles.thirdContainer}> <View style={styles.thirdContainer}>
<Text>No data found</Text> <ProgressChart
data={data}
width={width}
height={220}
strokeWidth={16}
radius={32}
chartConfig={chartConfig}
hideLegend={false}
/>
</View>
<View style={styles.secondContainer} >
<Text style={styles.topTextMain}>Week Report</Text>
</View>
<View style={styles.secondContainer}>
<Text style={styles.SecondTextMain}>Not Found data</Text>
</View> </View>
</SafeAreaView> </SafeAreaView>
) )
...@@ -41,6 +81,7 @@ const styles = StyleSheet.create({ ...@@ -41,6 +81,7 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
paddingHorizontal: 10, paddingHorizontal: 10,
marginTop: 20
}, },
topTextMain: { topTextMain: {
marginTop: 15, marginTop: 15,
...@@ -49,11 +90,18 @@ const styles = StyleSheet.create({ ...@@ -49,11 +90,18 @@ const styles = StyleSheet.create({
marginLeft: 10, marginLeft: 10,
color: "black" color: "black"
}, },
SecondTextMain: {
marginTop: 15,
fontSize: 15,
marginLeft: 10,
color: "black"
},
thirdContainer: { thirdContainer: {
alignItems: "center", alignItems: "center",
textAlign: "center", textAlign: "center",
height: "30%", height: "30%",
marginTop: "20%" marginTop: "10%",
marginHorizontal: 20
} }
}) })
export default ExercisesProgress export default ExercisesProgress
\ No newline at end of file
...@@ -24,6 +24,28 @@ const HealthFormExercise = (props) => { ...@@ -24,6 +24,28 @@ const HealthFormExercise = (props) => {
const [wearableModalVisible, setWearableModalVisible] = useState(false); const [wearableModalVisible, setWearableModalVisible] = useState(false);
const validateInputs = (values) => {
const errors = {};
if (!values.SystolicBP || isNaN(values.SystolicBP) || values.SystolicBP <= 0 || values.SystolicBP > 180) {
errors.SystolicBP = 'Invalid Systolic Blood Pressure (1-180)';
}
if (!values.DiastolicBP || isNaN(values.DiastolicBP) || values.DiastolicBP <= 0 || values.DiastolicBP > 120) {
errors.DiastolicBP = 'Invalid Diastolic Blood Pressure (1-120)';
}
if (!values.Blood_glucose || isNaN(values.Blood_glucose) || values.Blood_glucose <= 0 || values.Blood_glucose > 18) {
errors.Blood_glucose = 'Invalid Blood Glucose (1-400)';
}
if (!values.BodyTemp || isNaN(values.BodyTemp) || values.BodyTemp <= 0 || values.BodyTemp > 113) {
errors.BodyTemp = 'Invalid Body Temperature (1-45)';
}
if (!values.HeartRate || isNaN(values.HeartRate) || values.HeartRate <= 0 || values.HeartRate > 200) {
errors.HeartRate = 'Invalid Heart Rate (1-200)';
}
return errors;
};
useEffect(() => { useEffect(() => {
if (isWearbleDevice) { if (isWearbleDevice) {
const databaseRef = database().ref('test'); const databaseRef = database().ref('test');
...@@ -54,6 +76,12 @@ const HealthFormExercise = (props) => { ...@@ -54,6 +76,12 @@ const HealthFormExercise = (props) => {
} }
const onSubmit = async (values) => { const onSubmit = async (values) => {
const errors = validateInputs(values);
if (Object.keys(errors).length > 0) {
ToastAndroid.show(Object.values(errors).join(', '), ToastAndroid.LONG);
return;
}
let userDataString = await AsyncStorage.getItem('userData'); let userDataString = await AsyncStorage.getItem('userData');
let userData = JSON.parse(userDataString); let userData = JSON.parse(userDataString);
console.log(values) console.log(values)
...@@ -86,6 +114,7 @@ const HealthFormExercise = (props) => { ...@@ -86,6 +114,7 @@ const HealthFormExercise = (props) => {
ToastAndroid.show('Error updating userData !', ToastAndroid.SHORT); ToastAndroid.show('Error updating userData !', ToastAndroid.SHORT);
} }
} }
return ( return (
<SafeAreaView > <SafeAreaView >
<Formik <Formik
......
// // cloudinary.js
// import { Cloudinary } from 'cloudinary-core';
// const cloudinary = new Cloudinary({
// cloud_name: 'dehjozc3p',
// api_key: '381783681172934',
// api_secret: '438Ho1zc1fje40TJplqtpj3wzGU'
// });
// export default cloudinary;
import axios from "axios"; import axios from "axios";
let BASE_PATH = 'http://16.170.242.186:8080'; let BASE_PATH = 'http://16.170.242.186:8080';
let SECOND_BASE_PATH = 'http://16.171.16.144:8070/api/mother'; let SECOND_BASE_PATH = 'http://16.171.16.144:8070/api/mother';
let THIRD_BASE_PATH = 'http://51.20.73.24:8000';
import AsyncStorage from '@react-native-async-storage/async-storage'; import AsyncStorage from '@react-native-async-storage/async-storage';
...@@ -58,3 +59,15 @@ export let updateDeviceStatus = async (id, deviceStatus) => { ...@@ -58,3 +59,15 @@ export let updateDeviceStatus = async (id, deviceStatus) => {
return error return error
} }
} }
export let updatePoseCountStatus = async (url, mode) => {
try {
let value = await axios.post(THIRD_BASE_PATH + '/video_feed', {
video_url: url,
exercise_mode: mode
})
return value;
} catch (error) {
return error
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment