Add Acvities component

View_Tony-Theme
Tony Fages 5 months ago
parent cd81642bb6
commit 767ea1aa67

@ -1,51 +1,53 @@
import {Image, SafeAreaView, Text, TouchableOpacity, View} from "react-native";
import {SafeAreaView, ScrollView, Text, View} from "react-native";
import React from "react";
import {Ionicons} from "@expo/vector-icons";
import WorkoutCardComponent from "@/components/WorkoutCardComponent";
import Screen from "@/components/ui/Screen";
import CalendarComponent from "@/components/CalendarComponent";
import WelcomeComponent from "@/components/WelcomeComponent";
import ActivitiesComponent from "@/components/ActivitiesComponent";
export default function HomeScreen() {
const date = new Date();
const formattedDate = date.toLocaleDateString('fr-FR', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
return (
<SafeAreaView>
<View className="bg-black p-4 rounded-b-2xl h-auto">
<View className="flex-row m-4 ">
<Ionicons name="calendar" size={24} color="white" />
<Text className="text-gray-400 text-2xl mb-2 ml-1">{formattedDate}</Text>
<Screen>
<ScrollView>
<View >
<WelcomeComponent/>
</View>
<View className="flex-row items-center justify-between m-2">
<View className="flex-row items-center">
<Image className="h-20 w-24 rounded-2xl"
source={require("assets/images/sigma-profile.jpeg")}
/>
<Text className="text-white text-4xl font-extrabold ml-2 ">Hello, Tata Yoyo!</Text>
<View className="mt-2">
<View className="flex-row justify-between items-center mb-4">
<Text className="text-lg font-bold text-black">Activities</Text>
<Text className="text-orange-500 font-semibold">See All</Text>
</View>
{/* Notifications */}
<TouchableOpacity>
{/* Notification Badge */}
<View className="absolute top-0 right-0 bg-red-500 w-4 h-4 rounded-full flex items-center justify-center m-4">
<Ionicons name="notifications" size={16} color="white" />
<Text className="text-white text-xs font-bold">8</Text>
</View>
</TouchableOpacity>
<ActivitiesComponent/>
</View>
</View>
<View className="mt-2">
<View className="flex-row justify-between items-center mb-4">
<Text className="text-lg font-bold text-black">Fitness Metrics</Text>
<Text className="text-orange-500 font-semibold">See All</Text>
</View>
<CalendarComponent/>
</View>
<View>
<View className="mt-2">
<View className="flex-row justify-between items-center mb-4">
<Text className="text-lg font-bold text-black">Workout</Text>
<Text className="text-orange-500 font-semibold">See All</Text>
</View>
<WorkoutCardComponent/>
</View>
</ScrollView>
</Screen>
</SafeAreaView>
);
}

@ -0,0 +1,111 @@
import {Text, TouchableOpacity, View} from "react-native";
import {CurveType, LineChart} from "react-native-gifted-charts";
import React, {useRef, useState} from "react";
export default function ActivitiesComponent() {
const ref = useRef(null)
const [dateSelected, setDateSelected] = useState('1d');
const [lineData, setLineData] = useState([
{value: 4},
{value: 14},
{value: 8},
{value: 38},
{value: 36},
{value: 28},
]);
const months = ['1d','1w','1m','1y','All']
const changeMonthSelected = (ind) => {
const selectedMonth = months[ind];
setDateSelected(selectedMonth);
// Update lineData based on the selected month
let newData;
switch (selectedMonth) {
case '1d':
newData = [
{value: 4},
{value: 14},
{value: 8},
{value: 38},
{value: 36},
{value: 28},
];
break;
case '1w':
newData = [
{value: 8},
{value: 14},
{value: 8},
{value: 38},
{value: 14},
{value: 28},
{value: 4},
];
break;
case '1m':
newData = [
{value: 10},
{value: 20},
{value: 30},
{value: 40},
{value: 50},
{value: 60},
];
break;
case '1y':
newData = [
{value: 15},
{value: 25},
{value: 35},
{value: 45},
{value: 55},
{value: 65},
];
break;
case 'All':
newData = [
{value: 5},
{value: 15},
{value: 25},
{value: 35},
{value: 45},
{value: 55},
];
break;
default:
newData = [];
}
setLineData(newData);
};
return (
<View className="bg-gray-200 rounded-2xl p-1">
<View className=" m-2 flex-row justify-center rounded-2xl bg-white">
{months.map((item, index) => {
return (
<TouchableOpacity
key={index}
className={`w-16 h-10 flex items-center justify-center rounded-xl ${
dateSelected === item
? "bg-orange-500 border-2 border-orange-300"
: "bg-transparent "
}`}
onPress={() => changeMonthSelected(index)}>
<Text className="font-extrabold">{months[index]}</Text>
</TouchableOpacity>
);
})}
</View>
<LineChart
scrollRef={ref}
data={lineData}
curved
initialSpacing={0}
rotateLabel
isAnimated={true}
curveType={CurveType.QUADRATIC}
/>
</View>
);
}

@ -0,0 +1,51 @@
import {FlatList, TouchableOpacity,Text, View} from "react-native";
import {useState} from "react";
import dayjs from "dayjs";
export default function CalendarComponent() {
const [selectedDay] = useState(dayjs().date());
const days = Array.from({ length: 7 }, (_, index) => {
const day = dayjs().add(index, "day");
return {
id: day.date(),
label: day.format("ddd"),
};
});
return (
<View className="bg-transparent">
<FlatList
horizontal
data={days}
keyExtractor={(item) => item.id.toString()}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{ gap: 12 }} // Espacement entre les items
renderItem={({ item }) => (
<TouchableOpacity
className={`w-16 h-20 flex items-center justify-center rounded-xl ${
selectedDay === item.id
? "bg-orange-500 border-2 border-orange-300"
: "bg-black"
}`}
>
<Text
className={`text-sm ${
selectedDay === item.id ? "text-white" : "text-gray-400"
}`}
>
{item.label}
</Text>
<Text
className={`text-lg font-bold ${
selectedDay === item.id ? "text-white" : "text-gray-200"
}`}
>
{item.id}
</Text>
</TouchableOpacity>
)}
/>
</View>
);
}

@ -1,42 +0,0 @@
import React from "react";
import { Text } from "./ui/text";
import { Box } from "./ui/box";
import { ImageBackground } from "react-native";
import { HStack } from "@/components/ui/hstack";
import { Button } from "@/components/ui/Button";
import { AntDesign } from "@expo/vector-icons";
export default function ExerciceOverview() {
const exercise = {
name: "Jumping Jacks",
time: "00:30",
kcal: 5,
sets: 3,
difficulty: "Medium",
imageUri: "https://random-image-pepebigotes.vercel.app/api/random-image",
};
const image = { uri: exercise.imageUri };
return (
<Box className="h-1/4">
<ImageBackground source={image} imageStyle={{ borderRadius: 15 }}>
<HStack>
<Text className="font-extrabold text-black">{exercise.time}</Text>
<Text className="text-black">{exercise.kcal} kcal</Text>
</HStack>
<HStack>
<Box className="flex-1 items-start">
<Text className="text-black">{exercise.name}</Text>
<Text className="text-black">{exercise.sets} Sets</Text>
<Text className="text-black">{exercise.difficulty} Difficulty</Text>
</Box>
<Button className="bg-transparent items-end ">
<AntDesign name="play" size={24} />
</Button>
</HStack>
</ImageBackground>
</Box>
);
}

@ -0,0 +1,33 @@
import {Image, Text, TouchableOpacity, View} from "react-native";
import {Ionicons} from "@expo/vector-icons";
import React from "react";
export default function WelcomeComponent() {
const date = new Date();
const formattedDate = date.toLocaleDateString('fr-FR', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
return (
<View className="rounded-2xl overflow-hidden shadow-lg h-auto bg-black pb-4">
<View className="flex-row m-4 ">
<Ionicons name="calendar" size={24} color="white" />
<Text className="text-gray-400 text-2xl mb-2 ml-1">{formattedDate}</Text>
</View>
<View className="flex-row items-center justify-between m-2">
<View className="flex-row items-center">
<Image className="h-20 w-24 rounded-2xl"
source={require("assets/images/sigma-profile.jpeg")}
/>
<Text className="text-white text-4xl font-extrabold ml-2 ">Hello, Tata Yoyo!</Text>
</View>
</View>
</View>
);
}

@ -1,13 +1,18 @@
import {ImageBackground, SafeAreaView,Text, TouchableOpacity, View} from "react-native";
import React from "react";
import {AntDesign} from "@expo/vector-icons";
import {AntDesign, MaterialCommunityIcons} from "@expo/vector-icons";
import {Workout} from "@/model/Workout";
export default function WorkoutCardComponent() {
const exercise = new Workout("Faire caca par Terre", 25,"8 Series Workout", 412, "assets/images/Sigma-2.jpg","Intense" );
return (
<SafeAreaView>
<View>
<View className="rounded-2xl overflow-hidden shadow-lg h-72">
<ImageBackground
source={require("assets/images/Sigma-2.jpg")}
className="w-full h-full"
@ -16,17 +21,20 @@ export default function WorkoutCardComponent() {
<View className="flex-row justify-between items-center p-4">
<View className="flex-row space-x-4">
<View className="flex-row items-center">
<Text className="text-white text-sm ml-1">25min</Text>
<Text className="text-white text-sm ml-1">{exercise.duration} min</Text>
</View>
<View className="justify-center ml-0.5">
<MaterialCommunityIcons name="square-rounded" size={8}color="white" />
</View>
<View className="flex-row items-center">
<Text className="text-white text-sm ml-1">412kcal</Text>
<Text className="text-white text-sm ml-1">{exercise.calories} kcal</Text>
</View>
</View>
</View>
<View className="absolute bottom-0 left-0 right-0 p-4 bg-black bg-opacity-50">
<Text className="text-white text-lg font-bold">Faire caca par Terre</Text>
<Text className="text-gray-300 text-sm">8 Series Workout</Text>
<Text className="text-white text-lg font-bold">{exercise.name}</Text>
<Text className="text-gray-300 text-sm">{exercise.repetitions}</Text>
<View className="flex-row items-center mt-2">
<Text className="text-white text-xs bg-gray-800 py-1 px-3 rounded-full">
Intense
@ -34,12 +42,11 @@ export default function WorkoutCardComponent() {
</View>
</View>
<TouchableOpacity className="absolute bottom-4 right-4 p-4 rounded-full">
<AntDesign name="play" size={24} color="white" />
<TouchableOpacity className="absolute bottom-2 right-4 p-4 rounded-full">
<AntDesign name="play" size={50} color="orange" />
</TouchableOpacity>
</ImageBackground>
</View>
</View>
</SafeAreaView>
);
}

@ -0,0 +1,43 @@
export class Workout {
private _name: string
private _duration: number
private _calories: number
private _repetitions: string
private _image: string
private _level: string
get name(): string {
return this._name;
}
get duration(): number {
return this._duration;
}
get calories(): number {
return this._calories;
}
get repetitions(): string {
return this._repetitions;
}
get image(): string {
return this._image;
}
get level(): string {
return this._level;
}
constructor(name: string, duration: number, repetition: string, calories: number, image: string, level: string) {
this._name = name;
this._duration = duration;
this._repetitions = repetition
this._calories = calories;
this._image = image;
this._level = level;
}
}

56
package-lock.json generated

@ -14,12 +14,14 @@
"@react-navigation/native": "^7.0.14",
"@react-navigation/native-stack": "^7.2.0",
"@react-navigation/stack": "^7.1.1",
"dayjs": "^1.11.13",
"expo": "^52.0.24",
"expo-asset": "^11.0.2",
"expo-blur": "^14.0.1",
"expo-constants": "^17.0.3",
"expo-font": "^13.0.2",
"expo-haptics": "^14.0.0",
"expo-linear-gradient": "~14.0.2",
"expo-linking": "^7.0.3",
"expo-router": "~4.0.16",
"expo-secure-store": "^14.0.1",
@ -33,10 +35,11 @@
"react-dom": "18.3.1",
"react-native": "0.76.6",
"react-native-gesture-handler": "^2.20.2",
"react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "^4.4.0",
"react-native-svg": "^15.8.0",
"react-native-svg": "15.8.0",
"react-native-vector-icons": "^10.2.0",
"react-native-web": "^0.19.13",
"react-native-webview": "13.12.5",
@ -5985,6 +5988,12 @@
"node": ">=12"
}
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
@ -6833,6 +6842,17 @@
"react": "*"
}
},
"node_modules/expo-linear-gradient": {
"version": "14.0.2",
"resolved": "https://registry.npmjs.org/expo-linear-gradient/-/expo-linear-gradient-14.0.2.tgz",
"integrity": "sha512-nvac1sPUfFFJ4mY25UkvubpUV/olrBH+uQw5k+beqSvQaVQiUfFtYzfRr+6HhYBNb4AEsOtpsCRkpDww3M2iGQ==",
"license": "MIT",
"peerDependencies": {
"expo": "*",
"react": "*",
"react-native": "*"
}
},
"node_modules/expo-linking": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/expo-linking/-/expo-linking-7.0.4.tgz",
@ -7562,6 +7582,16 @@
"node": ">=6"
}
},
"node_modules/gifted-charts-core": {
"version": "0.1.56",
"resolved": "https://registry.npmjs.org/gifted-charts-core/-/gifted-charts-core-0.1.56.tgz",
"integrity": "sha512-Gey9dxjUB4/4bCin+xSyLuudSoBffJ9GK1qd0epBd3vrjHMGYrKFNRlkxI5MRxIJjvTcWOL2Fi43glNC2gs/0w==",
"license": "MIT",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@ -12191,6 +12221,30 @@
"react-native": "*"
}
},
"node_modules/react-native-gifted-charts": {
"version": "1.4.54",
"resolved": "https://registry.npmjs.org/react-native-gifted-charts/-/react-native-gifted-charts-1.4.54.tgz",
"integrity": "sha512-FvDRbymuJMxpsPbveQqyLUIYzfgJeY6xC6hNYD0d1OLZdnv/HgNYFMIwpoh2Hv25GRS0BXwPLjf8zE0f2zY9Wg==",
"license": "MIT",
"dependencies": {
"gifted-charts-core": "0.1.56"
},
"peerDependencies": {
"expo-linear-gradient": "*",
"react": "*",
"react-native": "*",
"react-native-linear-gradient": "*",
"react-native-svg": "*"
},
"peerDependenciesMeta": {
"expo-linear-gradient": {
"optional": true
},
"react-native-linear-gradient": {
"optional": true
}
}
},
"node_modules/react-native-helmet-async": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/react-native-helmet-async/-/react-native-helmet-async-2.0.4.tgz",

@ -21,12 +21,14 @@
"@react-navigation/native": "^7.0.14",
"@react-navigation/native-stack": "^7.2.0",
"@react-navigation/stack": "^7.1.1",
"dayjs": "^1.11.13",
"expo": "^52.0.24",
"expo-asset": "^11.0.2",
"expo-blur": "^14.0.1",
"expo-constants": "^17.0.3",
"expo-font": "^13.0.2",
"expo-haptics": "^14.0.0",
"expo-linear-gradient": "~14.0.2",
"expo-linking": "^7.0.3",
"expo-router": "~4.0.16",
"expo-secure-store": "^14.0.1",
@ -40,10 +42,11 @@
"react-dom": "18.3.1",
"react-native": "0.76.6",
"react-native-gesture-handler": "^2.20.2",
"react-native-gifted-charts": "^1.4.54",
"react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "^4.4.0",
"react-native-svg": "^15.8.0",
"react-native-svg": "15.8.0",
"react-native-vector-icons": "^10.2.0",
"react-native-web": "^0.19.13",
"react-native-webview": "13.12.5",

Loading…
Cancel
Save