diff --git a/app/_layout.tsx b/app/_layout.tsx index da0ddcb..55d43ba 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,53 +1,118 @@ -import {Stack, Tabs} from "expo-router"; - import "../global.css"; import { GluestackUIProvider } from "./src/components/ui/gluestack-ui-provider"; import HomeScreen from "@/src/screen/HomeScreen"; import ProfileScreen from "@/src/screen/ProfileScreen"; import React from "react"; -import Navigation from "@/src/navigation/navigation"; -import {SafeAreaView} from "react-native"; -import {createBottomTabNavigator} from "@react-navigation/bottom-tabs"; -import {AntDesign, MaterialIcons} from "@expo/vector-icons"; +import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; +import { + AntDesign, + Entypo, + MaterialCommunityIcons, + MaterialIcons, +} from "@expo/vector-icons"; + export default function RootLayout() { const BottomTabNavigator = createBottomTabNavigator(); return ( - - - + ( - + + + tabBarIcon: ({ color, size, focused }) => ( + + ), }} /> - ( - - ), - }}/> + ( + + ), + }} + /> - - - ); -} + ( + + ), + tabBarItemStyle: { + borderRadius: 50, + backgroundColor: "orange", + }, + }} + /> + ( + + ), + }} + /> + ( + + ), + }} + /> + + + ); +} diff --git a/app/src/components/ui/avatar/index.tsx b/app/src/components/ui/avatar/index.tsx new file mode 100644 index 0000000..c11b3f7 --- /dev/null +++ b/app/src/components/ui/avatar/index.tsx @@ -0,0 +1,186 @@ +'use client'; +import React from 'react'; +import { createAvatar } from '@gluestack-ui/avatar'; + +import { View, Text, Image, Platform } from 'react-native'; + +import { tva } from '@gluestack-ui/nativewind-utils/tva'; +import { + withStyleContext, + useStyleContext, +} from '@gluestack-ui/nativewind-utils/withStyleContext'; +const SCOPE = 'AVATAR'; +import type { VariantProps } from '@gluestack-ui/nativewind-utils'; + +const UIAvatar = createAvatar({ + Root: withStyleContext(View, SCOPE), + Badge: View, + Group: View, + Image: Image, + FallbackText: Text, +}); + +const avatarStyle = tva({ + base: 'rounded-full justify-center items-center relative bg-primary-600 group-[.avatar-group]/avatar-group:-ml-2.5', + variants: { + size: { + 'xs': 'w-6 h-6', + 'sm': 'w-8 h-8', + 'md': 'w-12 h-12', + 'lg': 'w-16 h-16', + 'xl': 'w-24 h-24', + '2xl': 'w-32 h-32', + }, + }, +}); + +const avatarFallbackTextStyle = tva({ + base: 'text-typography-0 font-semibold overflow-hidden text-transform:uppercase web:cursor-default', + + parentVariants: { + size: { + 'xs': 'text-2xs', + 'sm': 'text-xs', + 'md': 'text-base', + 'lg': 'text-xl', + 'xl': 'text-3xl', + '2xl': 'text-5xl', + }, + }, +}); + +const avatarGroupStyle = tva({ + base: 'group/avatar-group flex-row-reverse relative avatar-group', +}); + +const avatarBadgeStyle = tva({ + base: 'w-5 h-5 bg-success-500 rounded-full absolute right-0 bottom-0 border-background-0 border-2', + parentVariants: { + size: { + 'xs': 'w-2 h-2', + 'sm': 'w-2 h-2', + 'md': 'w-3 h-3', + 'lg': 'w-4 h-4', + 'xl': 'w-6 h-6', + '2xl': 'w-8 h-8', + }, + }, +}); + +const avatarImageStyle = tva({ + base: 'h-full w-full rounded-full absolute', +}); + +type IAvatarProps = Omit< + React.ComponentPropsWithoutRef, + 'context' +> & + VariantProps; + +const Avatar = React.forwardRef< + React.ElementRef, + IAvatarProps +>(({ className, size = 'md', ...props }, ref) => { + return ( + + ); +}); + +type IAvatarBadgeProps = React.ComponentPropsWithoutRef & + VariantProps; + +const AvatarBadge = React.forwardRef< + React.ElementRef, + IAvatarBadgeProps +>(({ className, size, ...props }, ref) => { + const { size: parentSize } = useStyleContext(SCOPE); + + return ( + + ); +}); + +type IAvatarFallbackTextProps = React.ComponentPropsWithoutRef< + typeof UIAvatar.FallbackText +> & + VariantProps; +const AvatarFallbackText = React.forwardRef< + React.ElementRef, + IAvatarFallbackTextProps +>(({ className, size, ...props }, ref) => { + const { size: parentSize } = useStyleContext(SCOPE); + + return ( + + ); +}); + +type IAvatarImageProps = React.ComponentPropsWithoutRef & + VariantProps; + +const AvatarImage = React.forwardRef< + React.ElementRef, + IAvatarImageProps +>(({ className, ...props }, ref) => { + return ( + + ); +}); + +type IAvatarGroupProps = React.ComponentPropsWithoutRef & + VariantProps; + +const AvatarGroup = React.forwardRef< + React.ElementRef, + IAvatarGroupProps +>(({ className, ...props }, ref) => { + return ( + + ); +}); + +export { Avatar, AvatarBadge, AvatarFallbackText, AvatarImage, AvatarGroup }; diff --git a/app/src/components/ui/box/index.tsx b/app/src/components/ui/box/index.tsx new file mode 100644 index 0000000..766266f --- /dev/null +++ b/app/src/components/ui/box/index.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { View, ViewProps } from 'react-native'; + +import type { VariantProps } from '@gluestack-ui/nativewind-utils'; +import { boxStyle } from './styles'; + +type IBoxProps = ViewProps & + VariantProps & { className?: string }; + +const Box = React.forwardRef, IBoxProps>( + ({ className, ...props }, ref) => { + return ( + + ); + } +); + +Box.displayName = 'Box'; +export { Box }; diff --git a/app/src/components/ui/box/index.web.tsx b/app/src/components/ui/box/index.web.tsx new file mode 100644 index 0000000..51b375b --- /dev/null +++ b/app/src/components/ui/box/index.web.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { boxStyle } from './styles'; + +import type { VariantProps } from '@gluestack-ui/nativewind-utils'; + +type IBoxProps = React.ComponentPropsWithoutRef<'div'> & + VariantProps & { className?: string }; + +const Box = React.forwardRef( + ({ className, ...props }, ref) => { + return ( +
+ ); + } +); + +Box.displayName = 'Box'; +export { Box }; diff --git a/app/src/components/ui/box/styles.tsx b/app/src/components/ui/box/styles.tsx new file mode 100644 index 0000000..760e8ff --- /dev/null +++ b/app/src/components/ui/box/styles.tsx @@ -0,0 +1,10 @@ +import { tva } from '@gluestack-ui/nativewind-utils/tva'; +import { isWeb } from '@gluestack-ui/nativewind-utils/IsWeb'; + +const baseStyle = isWeb + ? 'flex flex-col relative z-0 box-border border-0 list-none min-w-0 min-h-0 bg-transparent items-stretch m-0 p-0 text-decoration-none' + : ''; + +export const boxStyle = tva({ + base: baseStyle, +}); diff --git a/package-lock.json b/package-lock.json index 91d3c5e..94dabb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@expo/vector-icons": "^14.0.2", + "@gluestack-ui/avatar": "^0.1.18", "@gluestack-ui/button": "^1.0.8", "@gluestack-ui/icon": "^0.1.25", "@gluestack-ui/nativewind-utils": "^1.0.26", @@ -2383,6 +2384,18 @@ "tslib": "2" } }, + "node_modules/@gluestack-ui/avatar": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/@gluestack-ui/avatar/-/avatar-0.1.18.tgz", + "integrity": "sha512-VA9XwtavYLYCWrjxHc2u9gRpV97cPRcr/6KJ4tLiMiQbiRL1b4zckiL+/F39fB6xjUOUQHl3Fjo/Yd8swa0MBg==", + "dependencies": { + "@gluestack-ui/utils": "^0.1.14" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/@gluestack-ui/button": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@gluestack-ui/button/-/button-1.0.8.tgz", diff --git a/package.json b/package.json index bb93596..ff9bc02 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ }, "dependencies": { "@expo/vector-icons": "^14.0.2", + "@gluestack-ui/avatar": "^0.1.18", "@gluestack-ui/button": "^1.0.8", "@gluestack-ui/icon": "^0.1.25", "@gluestack-ui/nativewind-utils": "^1.0.26", diff --git a/src/component/ExerciceOverview.tsx b/src/component/ExerciceOverview.tsx new file mode 100644 index 0000000..2a4c4dd --- /dev/null +++ b/src/component/ExerciceOverview.tsx @@ -0,0 +1,50 @@ + +import React from "react"; +import {View, TouchableOpacity, ImageBackground, ImageBase} from "react-native"; +import { AntDesign } from "@expo/vector-icons"; // Assure-toi d'avoir installé les icônes +import { Text } from "@/app/src/components/ui/text"; + +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 ( + + + + {exercise.time} + {exercise.kcal} kcal + + + + {exercise.name} + {exercise.sets} Sets + {exercise.difficulty} Difficulty + + + + console.log("Play exercise started")} + > + + + + + + + + ); + +} \ No newline at end of file diff --git a/src/screen/HomeScreen.tsx b/src/screen/HomeScreen.tsx index 85856f3..023fdfb 100644 --- a/src/screen/HomeScreen.tsx +++ b/src/screen/HomeScreen.tsx @@ -1,13 +1,104 @@ -import {View, Text, SafeAreaView} from "react-native"; +import {SafeAreaView, StyleSheet, View} from "react-native"; +import React from "react"; +import {Avatar, AvatarFallbackText, AvatarImage,} from "@/app/src/components/ui/avatar" +import {AntDesign} from "@expo/vector-icons"; +import {Text} from "@/app/src/components/ui/text"; +import {Box} from "@/app/src/components/ui/box"; +import ExerciceOverview from "@/src/component/ExerciceOverview"; export default function HomeScreen() { + const date = new Date(); + const formattedDate = date.toLocaleDateString('fr-FR', { + year: 'numeric', + month: 'long', + day: 'numeric', + }); + return ( - - - Edit src/screen/HomeScreen.tsx to edit this screen. + + + + + {formattedDate} + + + + + Jane Doe + + + Hello, Tata Monique + + + + + + + - + ); -} \ No newline at end of file +} + + + +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: { + + } + + +}); \ No newline at end of file