Add view workout details

pull/19/head
Tony Fages 6 days ago
parent 753a2f5622
commit 019b67cce0

@ -1,14 +1,33 @@
import {SafeAreaView, View, Text} from "react-native";
import {SafeAreaView, View, Text, ImageBackground, TouchableOpacity} from "react-native";
import React from "react";
import InternalError from "@/components/error/InternalErrorProblem";
export default function AddScreen() {
return (
<ImageBackground
className="h-full w-full"
source={require("assets/images/TrainingPresentation.png")}
>
<SafeAreaView>
<View>
<InternalError/>
<View className="flex-row justify-between items-center mb-4">
<TouchableOpacity
className="bg-blue-500 px-4 py-2 rounded"
>
</TouchableOpacity>
<TouchableOpacity
className="bg-green-500 px-4 py-2 rounded"
>
<Text className="text-white font-bold">Action</Text>
</TouchableOpacity>
</View>
<View className="flex-1 items-center justify-center">
<Text className="text-xl font-semibold">Contenu de l'entraînement</Text>
</View>
</SafeAreaView>
</ImageBackground>
);
}

@ -1,97 +0,0 @@
// import { SafeAreaView, StyleSheet, View } from "react-native";
// import React from "react";
// import {
// Avatar,
// AvatarFallbackText,
// AvatarImage,
// } from "@/components/ui/avatar";
// import { AntDesign } from "@expo/vector-icons";
// import { Text } from "@/components/ui/text";
// import ExerciceOverview from "@/components/ExerciceOverview";
// export default function HomeScreen() {
// const date = new Date();
// const formattedDate = date.toLocaleDateString("fr-FR", {
// year: "numeric",
// month: "long",
// day: "numeric",
// });
// return (
// <SafeAreaView style={styles.container}>
// <View style={styles.headerStyle}>
// <View style={styles.dateContainer}>
// <AntDesign name="calendar" size={24} color="white" />
// <Text style={styles.dateText}>{formattedDate}</Text>
// </View>
// <View style={styles.avatarContainer}>
// <Avatar size="xl">
// <AvatarFallbackText>Jane Doe</AvatarFallbackText>
// <AvatarImage
// source={{
// uri: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=687&q=80",
// }}
// />
// </Avatar>
// <Text style={styles.titleNameUser}>Hello, Tata Monique</Text>
// </View>
// </View>
// <View>
// <ExerciceOverview />
// </View>
// </SafeAreaView>
// );
// }
// const styles = StyleSheet.create({
// container: {
// flex: 1,
// backgroundColor: "#f9f9f9", // Fond de l'écran avec une couleur claire
// },
// headerStyle: {
// height: 200,
// backgroundColor: "#333333", // Gris foncé pour l'arrière-plan du header
// borderBottomEndRadius: 25,
// borderBottomStartRadius: 25,
// padding: 20,
// alignItems: "flex-start",
// justifyContent: "flex-start",
// },
// dateContainer: {
// flexDirection: "row",
// alignItems: "flex-start",
// marginBottom: 20,
// },
// dateText: {
// fontSize: 18,
// fontWeight: "bold",
// marginLeft: 10,
// color: "#ffffff",
// },
// avatarContainer: {
// marginBottom: 15,
// flexDirection: "row",
// alignItems: "center",
// },
// titleNameUser: {
// fontSize: 24,
// color: "#ffffff",
// fontWeight: "bold",
// marginLeft: 10,
// },
// contentContainer: {
// marginTop: 20,
// padding: 15,
// alignItems: "flex-start",
// },
// contentText: {
// fontSize: 16,
// color: "#333333", // Texte en gris foncé pour une bonne lisibilité
// textAlign: "center",
// },
// fitness: {},
// });

@ -1,56 +0,0 @@
import { getExercices } from "@/api/services/ExercicesServices";
import WorkoutPresentationComponent from "@/components/WorkoutPresentationComponent";
import { useRouter } from "expo-router";
import React, { useEffect, useState } from "react";
import { ActivityIndicator, Text, View } from "react-native";
export default function WorkoutScreen() {
const router = useRouter();
const [exercices, setExercices] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const loadExercices = async () => {
try {
const data = await getExercices();
setExercices(data);
} catch (err: any) {
setError(err.message);
} finally {
setLoading(false);
}
};
loadExercices();
}, []);
if (loading) {
return (
<View className="flex-1 justify-center items-center bg-black">
<ActivityIndicator size="large" color="#fff" />
</View>
);
}
if (error) {
return (
<View className="flex-1 justify-center items-center bg-black">
<Text className="text-red-500 text-xl">{error}</Text>
</View>
);
}
const workout = exercices[1]; // Choisis lexercice que tu souhaites afficher
return (
<View className="h-full rounded-2xl">
<WorkoutPresentationComponent
workout={workout}
dataExercise={exercices}
router={router}
/>
</View>
);
}

@ -1,19 +0,0 @@
import React from "react";
import {Stack} from "expo-router";
export default function RootoLayout() {
return (
<Stack screenOptions={{
headerShown: false,
}}
initialRouteName={"ExercicesScreen"}
>
<Stack.Screen name="ExercicesScreen" />
<Stack.Screen name="WorkoutScreen"/>
</Stack>
);
}

@ -1,9 +1,9 @@
import { getExercices } from "@/api/services/ExercicesServices";
import WorkoutCardComponent from "@/components/WorkoutCardComponent";
import { Workout } from "@/model/Workout";
import { useRouter } from "expo-router";
import {useNavigation, useRouter} from "expo-router";
import React, { useEffect, useState } from "react";
import { FlatList, Text, TouchableOpacity, View } from "react-native";
import {FlatList, SafeAreaView, Text, TouchableOpacity, View} from "react-native";
export default function ExercicesScreen() {
const [exercices, setExercices] = useState<Workout[]>([]);
@ -35,24 +35,18 @@ export default function ExercicesScreen() {
}
return (
<View className="p-4">
<SafeAreaView>
<FlatList
data={exercices}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<TouchableOpacity
className="p-4 mb-2 bg-gray-800 rounded-lg"
onPress={() =>
router.push({
pathname: "/WorkoutScreen",
params: { workout: JSON.stringify(item) },
})
}
className="flex-1 m-2"
>
<WorkoutCardComponent exercise={item} background={"black"} />
</TouchableOpacity>
)}
/>
</View>
</SafeAreaView>
);
}

@ -0,0 +1,156 @@
import React, { useState } from "react";
import { View, Text, ImageBackground, TouchableOpacity, ScrollView, Dimensions, Image } from "react-native";
import Modal from "react-native-modal";
import { Ionicons } from "@expo/vector-icons";
import {useWorkoutStore} from "@/store/workoutStore";
import {Workout} from "@/model/Workout";
import {useRouter} from "expo-router";
const screenHeight = Dimensions.get("window").height;
export default function WorkoutScreen() {
const router = useRouter();
const workout = useWorkoutStore((s) => s.selectedWorkout);
const [isModalVisible, setModalVisible] = useState(false);
if (!workout) return <Text>Pas de workout</Text>;
const exercises: any[] = [
{
id: "1",
title: "Back Warmup",
duration: "05:30",
},
{
id: "2",
title: "Bent Over Row",
duration: "10:00",
},
{
id: "3",
title: "Renegade Row",
duration: "08:45",
},
];
return (
<View className="flex-1 bg-black">
<ImageBackground
source={require("assets/images/TrainingPresentation.png")}
className="flex-1 justify-between px-6 pb-10 pt-14"
imageStyle={{ resizeMode: "cover" }}
>
<View className="flex-row justify-between">
<TouchableOpacity className="bg-black/50 p-2 rounded-full">
<Ionicons name="chevron-back" size={20} color="white" />
</TouchableOpacity>
<TouchableOpacity className="bg-black/50 p-2 rounded-full">
<Ionicons name="settings-outline" size={20} color="white" />
</TouchableOpacity>
</View>
<View className="flex-1 justify-end">
<View className="items-center">
<View className="bg-black/50 px-6 py-2 rounded-full mb-4">
<Text className="text-white text-base">{exercises.length} Total</Text>
</View>
<Text className="text-white text-4xl font-bold">{workout.name}</Text>
</View>
<View className="flex-row justify-between mb-16 mt-16">
<View className="items-center flex-1">
<Ionicons name="time-outline" size={36} color="white" />
<Text className="text-white font-bold text-xl mt-2">{workout.duration} min</Text>
<Text className="text-gray-300 text-lg">Time</Text>
</View>
<View className="h-20 w-1 bg-white mx-2" />
<View className="items-center flex-1">
<Ionicons name="flame-outline" size={36} color="white" />
<Text className="text-white font-bold text-xl mt-2">240kcal</Text>
<Text className="text-gray-300 text-lg">Calories</Text>
</View>
<View className="h-20 w-1 bg-white mx-2" />
<View className="items-center flex-1">
<Ionicons name="barbell-outline" size={36} color="white" />
<Text className="text-white font-bold text-xl mt-2">{workout.nbRepetitions}</Text>
<Text className="text-gray-300 text-lg">Sets</Text>
</View>
</View>
</View>
<View className="flex-row">
<TouchableOpacity
className="flex-1 bg-black/50 p-4 rounded-xl flex-row justify-center items-center"
onPress={() => setModalVisible(true)}
>
<Text className="text-white mr-2">Details</Text>
<Ionicons name="document-text-outline" size={18} color="white" />
</TouchableOpacity>
<TouchableOpacity className="flex-1 bg-orange-500 p-4 rounded-xl flex-row justify-center items-center">
<Text className="text-white font-bold mr-2">Start</Text>
<Ionicons name="timer-outline" size={18} color="white" />
</TouchableOpacity>
</View>
</ImageBackground>
<Modal
isVisible={isModalVisible}
onBackdropPress={() => setModalVisible(false)}
swipeDirection="down"
onSwipeComplete={() => setModalVisible(false)}
style={{
justifyContent: "flex-end",
margin: 0,
}}
>
<View
style={{
height: screenHeight * 0.65,
backgroundColor: "white",
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
padding: 20,
}}
>
<ScrollView>
<Text className="text-center text-gray-700 mb-4">
Liste des exercices
</Text>
{exercises.map((ex, index) => (
<View
key={ex.id}
className="flex-row bg-gray-100 rounded-xl items-center p-3 mb-4"
>
<Image source={require("assets/images/TrainingPresentation.png")} className="w-16 h-16 rounded-md mr-3" />
<View className="flex-1">
<Text className="font-semibold text-black">
{index + 1}. {ex.title}
</Text>
<View className="flex-row items-center mt-1">
<Ionicons name="time-outline" size={14} color="gray" />
<Text className="text-gray-500 text-xs ml-1">{ex.duration}</Text>
</View>
</View>
<TouchableOpacity
onPress={() => {
// router.push("/(tabs)/(exercice)/ExercicesScreen")
}}>
<Ionicons name="play-circle" size={30} color="#ff7a00" />
</TouchableOpacity>
</View>
))}
</ScrollView>
</View>
</Modal>
</View>
);
}

@ -0,0 +1,32 @@
import {router, useLocalSearchParams} from 'expo-router';
import { View, Text, Image } from 'react-native';
import { useEffect, useState } from 'react';
import {Workout} from "@/model/Workout";
import WorkoutPresentationComponent from "@/components/WorkoutPresentationComponent";
export default function WorkoutScreen() {
const params = useLocalSearchParams();
const [workout, setWorkout] = useState<Workout | null>(null);
useEffect(() => {
if (typeof params.workout === 'string') {
try {
const parsed = JSON.parse(params.workout);
setWorkout(parsed);
} catch (error) {
}
}
}, []);
if (!workout) {
return <Text style={{ padding: 20, margin: 30 }}>Aucune donnée reçue.</Text>;
}
return (
<View>
<WorkoutPresentationComponent
workout={workout}
/>r
</View>
);
}

@ -0,0 +1,16 @@
import React from "react";
import {Stack} from "expo-router";
export default function RootoLayout() {
return (
<Stack
screenOptions={{
headerShown: false,
}}
initialRouteName="ExercicesScreen"
>
<Stack.Screen name="ExercicesScreen" />
<Stack.Screen name="WorkoutScreen" />
</Stack>
);
}

@ -22,6 +22,7 @@ export default function TabBarLayout() {
}
return (
<Tabs
screenOptions={{
headerShown: false,
@ -38,7 +39,7 @@ export default function TabBarLayout() {
/>
<Tabs.Screen
name="(exercice)"
name="(workout)"
options={{
tabBarShowLabel: false,
tabBarIcon: () => (

@ -6,7 +6,6 @@ import { Slot } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { useEffect } from "react";
// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
@ -21,9 +20,7 @@ export default function RootLayout() {
}
}, [loaded]);
if (!loaded) {
return null;
}
if (!loaded) return null;
return (
<SessionProvider>

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -4,6 +4,8 @@ import { useRouter } from "expo-router";
import React from "react";
import Text from "@/components/ui/Text"
import {ImageBackground, TouchableOpacity, View} from "react-native";
import {useWorkoutStore} from "@/store/workoutStore";
import {getState} from "jest-circus";
interface WorkoutCardComponentProps {
exercise?: Workout;
@ -11,18 +13,8 @@ interface WorkoutCardComponentProps {
height?: number;
}
export default function WorkoutCardComponent({
exercise,
height,
background,
}: WorkoutCardComponentProps) {
const style = () => {
return `h-full rounded-2xl overflow-hidden ${background ?? "bg-black"}`;
};
export default function WorkoutCardComponent({exercise}: WorkoutCardComponentProps) {
const styleImage = () => {
return `w-full h-full `;
};
const router = useRouter();
return (
<View className="h-full rounded-2xl overflow-hidden bg-black">
@ -66,7 +58,10 @@ export default function WorkoutCardComponent({
<TouchableOpacity
className="absolute bottom-2 right-4 p-4 rounded-full"
onPress={() => {
router.push("/WorkoutScreen");
if (exercise) {
useWorkoutStore.getState().setWorkout(exercise);
}
router.push('/WorkoutDetailScreen');
}}
>
<AntDesign name="play" size={50} color="orange" />

@ -8,8 +8,6 @@ import { ImageBackground, Text, TouchableOpacity, View } from "react-native";
type WorkoutPresentationComponentProps = {
workout: Workout;
dataExercise: Workout[];
router: Router; // Typage précis recommandé selon ta navigation
};
export default function WorkoutPresentationComponent({
@ -23,11 +21,10 @@ export default function WorkoutPresentationComponent({
>
<Screen>
<View className="flex-col h-full justify-between">
{/* Bouton Retour */}
<View className="mt-5 ml-5">
<TouchableOpacity
onPress={() => {
router.replace("/ExercicesScreen");
router.back();
}}
>
<Ionicons
@ -38,10 +35,8 @@ export default function WorkoutPresentationComponent({
</TouchableOpacity>
</View>
{/* Permet de pousser le reste du contenu vers le bas */}
<View className="flex-grow" />
{/* Texte en bas */}
<View className="items-center mb-10">
<Text className="text-white bg-transparent border-2 border-white px-3 py-1 rounded-full text-2xl font-bold">
{workout.nbSeries} x {workout.nbRepetitions}

@ -0,0 +1,16 @@
import {TargetEnum} from "@/model/enums/Target.enum";
export interface Exercice {
id: string;
name: string;
description: string;
target: TargetEnum;
image: string;
video: string;
duration: number;
nbSeries: number;
restTime: number;
nbRepetitions: number;
weight: number;
passed: boolean;
}

@ -0,0 +1,10 @@
import {Exercice} from "@/model/Exercice";
import {CategoryEnum} from "@/model/enums/Category.enum";
export interface Session {
id: string;
name: string;
description: string;
category: CategoryEnum;
exercises: Exercice[];
}

@ -0,0 +1,8 @@
import {Session} from "@/model/Session";
export interface Training {
id: string;
name: string;
description: string;
sessions: Session[];
}

@ -0,0 +1,6 @@
export enum CategoryEnum {
NONE = 'none',
TRAINING = 'training',
STRETCHING = 'stretching',
WARMUP = 'warmup'
}

@ -0,0 +1,8 @@
export enum TargetEnum {
NONE = 'none',
ARM= 'arms',
BACK = 'back',
CARDIO = 'cardio',
CHEST = 'chest',
LEG = 'legs'
}

119
package-lock.json generated

@ -10,6 +10,7 @@
"dependencies": {
"@expo/html-elements": "^0.4.2",
"@expo/vector-icons": "^14.0.2",
"@gorhom/bottom-sheet": "^5.1.5",
"@react-native-community/slider": "4.5.6",
"@react-native-segmented-control/segmented-control": "2.5.7",
"@react-navigation/bottom-tabs": "^7.2.0",
@ -41,7 +42,8 @@
"react-native-element-dropdown": "^2.12.4",
"react-native-gesture-handler": "~2.24.0",
"react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "^3.16.1",
"react-native-modal": "^14.0.0-rc.1",
"react-native-reanimated": "^3.17.5",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "^4.4.0",
"react-native-svg": "15.11.2",
@ -49,13 +51,15 @@
"react-native-web": "^0.20.0",
"react-native-webview": "13.13.5",
"tailwindcss": "^3.4.17",
"validator": "^13.12.0"
"validator": "^13.12.0",
"zustand": "^5.0.4"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/jest": "^29.5.12",
"@types/react": "~19.0.10",
"@types/react-native": "^0.72.8",
"@types/react-native-vector-icons": "^6.4.18",
"@types/react-test-renderer": "^19.0.0",
"@types/validator": "^13.12.2",
"jest": "^29.2.1",
@ -2050,6 +2054,45 @@
"@babel/highlight": "^7.10.4"
}
},
"node_modules/@gorhom/bottom-sheet": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/@gorhom/bottom-sheet/-/bottom-sheet-5.1.5.tgz",
"integrity": "sha512-zn7IZMsEyVehB+hSl+VxHjk62PERyvQheBvhPzeZU+82ozDZ+qRxyrWMKy5YBFGka7DDfDgoPUUCCiaIWFyqmg==",
"license": "MIT",
"dependencies": {
"@gorhom/portal": "1.0.14",
"invariant": "^2.2.4"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-native": "*",
"react": "*",
"react-native": "*",
"react-native-gesture-handler": ">=2.16.1",
"react-native-reanimated": ">=3.16.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-native": {
"optional": true
}
}
},
"node_modules/@gorhom/portal": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/@gorhom/portal/-/portal-1.0.14.tgz",
"integrity": "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A==",
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.1"
},
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -3719,6 +3762,27 @@
"@types/react": "*"
}
},
"node_modules/@types/react-native-vector-icons": {
"version": "6.4.18",
"resolved": "https://registry.npmjs.org/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.18.tgz",
"integrity": "sha512-YGlNWb+k5laTBHd7+uZowB9DpIK3SXUneZqAiKQaj1jnJCZM0x71GDim5JCTMi4IFkhc9m8H/Gm28T5BjyivUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*",
"@types/react-native": "^0.70"
}
},
"node_modules/@types/react-native-vector-icons/node_modules/@types/react-native": {
"version": "0.70.19",
"resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.19.tgz",
"integrity": "sha512-c6WbyCgWTBgKKMESj/8b4w+zWcZSsCforson7UdXtXMecG3MxCinYi6ihhrHVPyUrVzORsvEzK8zg32z4pK6Sg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-native/node_modules/@react-native/virtualized-lists": {
"version": "0.72.8",
"resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz",
@ -10480,6 +10544,15 @@
}
}
},
"node_modules/react-native-animatable": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.4.0.tgz",
"integrity": "sha512-DZwaDVWm2NBvBxf7I0wXKXLKb/TxDnkV53sWhCvei1pRyTX3MVFpkvdYBknNBqPrxYuAIlPxEp7gJOidIauUkw==",
"license": "MIT",
"dependencies": {
"prop-types": "^15.8.1"
}
},
"node_modules/react-native-css-interop": {
"version": "0.1.22",
"resolved": "https://registry.npmjs.org/react-native-css-interop/-/react-native-css-interop-0.1.22.tgz",
@ -10598,6 +10671,19 @@
"react-native": "*"
}
},
"node_modules/react-native-modal": {
"version": "14.0.0-rc.1",
"resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-14.0.0-rc.1.tgz",
"integrity": "sha512-v5pvGyx1FlmBzdHyPqBsYQyS2mIJhVmuXyNo5EarIzxicKhuoul6XasXMviGcXboEUT0dTYWs88/VendojPiVw==",
"license": "MIT",
"dependencies": {
"react-native-animatable": "1.4.0"
},
"peerDependencies": {
"react": "*",
"react-native": ">=0.70.0"
}
},
"node_modules/react-native-reanimated": {
"version": "3.17.5",
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.17.5.tgz",
@ -13135,6 +13221,35 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/zustand": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.4.tgz",
"integrity": "sha512-39VFTN5InDtMd28ZhjLyuTnlytDr9HfwO512Ai4I8ZABCoyAj4F1+sr7sD1jP/+p7k77Iko0Pb5NhgBFDCX0kQ==",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
},
"peerDependencies": {
"@types/react": ">=18.0.0",
"immer": ">=9.0.6",
"react": ">=18.0.0",
"use-sync-external-store": ">=1.2.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"immer": {
"optional": true
},
"react": {
"optional": true
},
"use-sync-external-store": {
"optional": true
}
}
}
}
}

@ -17,6 +17,7 @@
"dependencies": {
"@expo/html-elements": "^0.4.2",
"@expo/vector-icons": "^14.0.2",
"@gorhom/bottom-sheet": "^5.1.5",
"@react-native-community/slider": "4.5.6",
"@react-native-segmented-control/segmented-control": "2.5.7",
"@react-navigation/bottom-tabs": "^7.2.0",
@ -48,7 +49,8 @@
"react-native-element-dropdown": "^2.12.4",
"react-native-gesture-handler": "~2.24.0",
"react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "^3.16.1",
"react-native-modal": "^14.0.0-rc.1",
"react-native-reanimated": "^3.17.5",
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "^4.4.0",
"react-native-svg": "15.11.2",
@ -56,13 +58,15 @@
"react-native-web": "^0.20.0",
"react-native-webview": "13.13.5",
"tailwindcss": "^3.4.17",
"validator": "^13.12.0"
"validator": "^13.12.0",
"zustand": "^5.0.4"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/jest": "^29.5.12",
"@types/react": "~19.0.10",
"@types/react-native": "^0.72.8",
"@types/react-native-vector-icons": "^6.4.18",
"@types/react-test-renderer": "^19.0.0",
"@types/validator": "^13.12.2",
"jest": "^29.2.1",

@ -0,0 +1,14 @@
import {Workout} from "@/model/Workout";
import {create} from "zustand/react";
import {Exercice} from "@/model/Exercice";
type State = {
selectedExercice: Exercice | null;
setExercice: (exercice: Exercice) => void;
}
export const useExerciceStore = create<State>((set) => ({
selectedExercice: null,
setExercice: (exercice: Exercice) => set({ selectedExercice: exercice })
}));

@ -0,0 +1,12 @@
import {Workout} from "@/model/Workout";
import {create} from "zustand/react";
type State = {
selectedWorkout: Workout | null;
setWorkout: (workout: Workout) => void;
};
export const useWorkoutStore = create<State>((set) => ({
selectedWorkout: null,
setWorkout: (workout: Workout) => set({ selectedWorkout: workout }),
}));
Loading…
Cancel
Save