From 009eda1a6809d6a81f1592722e2b07a4fc99c38c Mon Sep 17 00:00:00 2001 From: Felix Ohnesorge Date: Sat, 4 May 2024 10:49:50 +0000 Subject: [PATCH] workouts --- frontend/app/home.tsx | 44 ++++++++++++--------- frontend/app/workout/[id].tsx | 5 ++- frontend/app/workout/create.tsx | 29 +++++++++++++- frontend/components/AddExerciseModal.tsx | 33 +++++++++------- frontend/components/HorizontalScollView.tsx | 24 +++++++++-- frontend/components/NumericInput.tsx | 13 +----- http-requests/workouts.http | 2 +- 7 files changed, 99 insertions(+), 51 deletions(-) diff --git a/frontend/app/home.tsx b/frontend/app/home.tsx index 30f6876..3195939 100644 --- a/frontend/app/home.tsx +++ b/frontend/app/home.tsx @@ -1,35 +1,40 @@ import { TouchableOpacity, Text, SafeAreaView } from 'react-native'; import { Stack, useRouter } from 'expo-router'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import ProfileButton from '../components/ProfileButton'; import styles from '../styles'; import Card from '../components/Card'; import AddCard from '../components/AddCard'; import HorizontalScrollView from '../components/HorizontalScollView'; import customFetch from '../customFetch'; +import { useFocusEffect } from '@react-navigation/native'; const HomeScreen = () => { const router = useRouter(); const [workouts, setWorkouts] = useState([]); - useEffect(() => { - const fetchWorkouts = async () => { - try { - const response = await customFetch( - 'http://192.168.178.79:3000/workouts/workouts', - ); - if (!response.ok) { - throw new Error('Failed to fetch workouts'); + useFocusEffect( + React.useCallback(() => { + const fetchWorkouts = async () => { + try { + const response = await customFetch( + 'http://192.168.178.79:3000/workouts/workouts', + ); + if (!response.ok) { + throw new Error('Failed to fetch workouts'); + } + const data = await response.json(); + setWorkouts(data.data); + } catch (error) { + console.error(error); } - const data = await response.json(); - setWorkouts(data.data); - } catch (error) { - console.error(error); - } - }; + }; - fetchWorkouts(); - }, []); + fetchWorkouts(); + + return () => {}; + }, []), + ); return ( <> @@ -41,7 +46,10 @@ const HomeScreen = () => { }} /> - + router.navigate('workouts')} + > {workouts.map((workout, index) => ( router.navigate(`/workout/${workout._id}`)} diff --git a/frontend/app/workout/[id].tsx b/frontend/app/workout/[id].tsx index 8ed3804..394cc5d 100644 --- a/frontend/app/workout/[id].tsx +++ b/frontend/app/workout/[id].tsx @@ -1,6 +1,6 @@ import { useLocalSearchParams } from 'expo-router'; import React, { useEffect, useState } from 'react'; -import { SafeAreaView, Text } from 'react-native'; +import { SafeAreaView, Text, TouchableOpacity } from 'react-native'; import styles from '../../styles'; import ExerciseCard from '../../components/ExerciseCard'; import HorizontalScrollView from '../../components/HorizontalScollView'; @@ -38,6 +38,9 @@ const WorkoutPage = () => { ))} + + Start Workout + ); }; diff --git a/frontend/app/workout/create.tsx b/frontend/app/workout/create.tsx index b775921..157f0bf 100644 --- a/frontend/app/workout/create.tsx +++ b/frontend/app/workout/create.tsx @@ -12,6 +12,7 @@ const CreateWorkout = () => { const router = useRouter(); const [name, setName] = useState(''); const [exercises, setExercises] = useState([]); + const [selectedExercise, setSelectedExercise] = useState(null); const [modalVisible, setModalVisible] = useState(false); const handleSubmit = async () => { @@ -45,10 +46,30 @@ const CreateWorkout = () => { }; const handleAddExercise = (exercise) => { + if (selectedExercise) { + handleUpdateExercise(exercise); + return; + } setExercises([...exercises, exercise]); setModalVisible(false); }; + const handleUpdateExercise = (updatedExercise) => { + setExercises( + exercises.map((exercise) => + exercise.id === updatedExercise.id ? updatedExercise : exercise, + ), + ); + setSelectedExercise(null); + setModalVisible(false); + }; + + const handleExerciseClick = (exercise) => { + // console.log(exercise); + setSelectedExercise(exercise); + setModalVisible(true); + }; + return ( Create a New Workout @@ -60,7 +81,12 @@ const CreateWorkout = () => { /> {exercises.map((exercise, index) => ( - + handleExerciseClick(exercise)} + > + + ))} setModalVisible(true)}> @@ -73,6 +99,7 @@ const CreateWorkout = () => { modalVisible={modalVisible} onClose={() => setModalVisible(false)} onAddExercise={handleAddExercise} + exercise={selectedExercise} /> ); diff --git a/frontend/components/AddExerciseModal.tsx b/frontend/components/AddExerciseModal.tsx index f963997..8b9c353 100644 --- a/frontend/components/AddExerciseModal.tsx +++ b/frontend/components/AddExerciseModal.tsx @@ -1,13 +1,24 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { Modal, Text, TextInput, TouchableOpacity } from 'react-native'; import styles from '../styles'; import { SafeAreaView } from 'react-native-safe-area-context'; import NumericInput from './NumericInput'; -const AddExerciseModal = ({ modalVisible, onClose, onAddExercise }) => { - const [exerciseName, setExerciseName] = useState(''); - const [reps, setReps] = useState(12); - const [sets, setSets] = useState(3); +const AddExerciseModal = ({ + modalVisible, + onClose, + onAddExercise, + exercise, +}) => { + const [exerciseName, setExerciseName] = useState(exercise?.name ?? null); + const [reps, setReps] = useState(exercise?.reps ?? 12); + const [sets, setSets] = useState(exercise?.sets ?? 3); + + useEffect(() => { + setExerciseName(exercise?.exercise.name || ''); + setReps(exercise?.reps || 12); + setSets(exercise?.sets || 3); + }, [exercise]); return ( { value={exerciseName} onChangeText={setExerciseName} /> - - + + diff --git a/frontend/components/HorizontalScollView.tsx b/frontend/components/HorizontalScollView.tsx index ff09886..e282311 100644 --- a/frontend/components/HorizontalScollView.tsx +++ b/frontend/components/HorizontalScollView.tsx @@ -1,11 +1,29 @@ import React from 'react'; -import { ScrollView, View, Text } from 'react-native'; +import { ScrollView, View, Text, TouchableOpacity } from 'react-native'; + import styles from '../styles'; -const HorizontalScrollView = ({ title, children }) => { +interface HorizontalScrollViewProps { + title: string; + children: React.ReactNode; + showAllAction?: () => void; +} + +const HorizontalScrollView: React.FC = ({ + title, + children, + showAllAction, +}) => { return ( - {title} + + {title} + {showAllAction && ( + + Show all + + )} + { - const [value, setValue] = useState(initialValue); - +const NumericInput = ({ title, value, onChange, min = 0, max = 100 }) => { const handleMinus = () => { if (value > min) { const newValue = value - 1; - setValue(newValue); onChange(newValue); } }; @@ -23,7 +13,6 @@ const NumericInput = ({ const handlePlus = () => { if (value < max) { const newValue = value + 1; - setValue(newValue); onChange(newValue); } }; diff --git a/http-requests/workouts.http b/http-requests/workouts.http index 6ef68fc..0a7e1d8 100644 --- a/http-requests/workouts.http +++ b/http-requests/workouts.http @@ -13,7 +13,7 @@ GET {{baseUrl}}/workouts/exercises ### -GET {{baseUrl}}/workouts/exercises?filter=bench +GET {{baseUrl}}/workouts/exercises ### # @name create_workout