Complete merge from master
continuous-integration/drone/push Build is passing Details

pull/23/head
Rémi REGNAULT 1 year ago
commit 09819727b4

@ -19,7 +19,7 @@ export default function App() {
<ColorProvider> <ColorProvider>
<NavigationContainer> <NavigationContainer>
<Tab.Navigator initialRouteName='HOME' tabBar={ (props) => <BottomBar {...props}/> }> <Tab.Navigator initialRouteName='HOME' tabBar={ (props) => <BottomBar {...props}/> }>
<Tab.Screen name='PROFILE' component={ProfilesStackScreen} options={{ headerShown: false, title: 'Profile' }} /> <Tab.Screen name='PROFILES' component={ProfilesStackScreen} options={{ headerShown: false, title: 'Profiles' }} />
<Tab.Screen name='HOME' component={HomeStackScreen} options={{ headerShown: false, title: 'Home' }}/> <Tab.Screen name='HOME' component={HomeStackScreen} options={{ headerShown: false, title: 'Home' }}/>
<Tab.Screen name='COOKING' component={CookingStackScreen} options={{ headerShown: false, title: 'Cooking' }}/> <Tab.Screen name='COOKING' component={CookingStackScreen} options={{ headerShown: false, title: 'Cooking' }}/>
</Tab.Navigator> </Tab.Navigator>

@ -1,20 +1,23 @@
export default class Profil { export default class Profil {
private _id: number;
private _name: string; private _name: string;
private _avatar: string;
private _allergy: string[]; private _allergy: string[];
private _diets: string[]; private _diets: string[];
constructor(id: number, name: string) { constructor( name: string, avatar: string, allergy: string[], diets: string[]) {
this._id = id;
this._name = name; this._name = name;
this._avatar = avatar;
this._allergy = allergy;
this._diets = diets;
} }
get name(): string { get name(): string {
return this._name; return this._name;
} }
get id(): number{
return this._id; get avatar(): string{
return this._avatar;
} }
get allergy(): string[]{ get allergy(): string[]{

@ -2,7 +2,7 @@ import Ingredient from "../../Models/Ingredient";
export default interface IIngredientService { export default interface IIngredientService {
getAllIngredient(): Promise<Ingredient[]>; getAllIngredient(): Promise<Ingredient[]>;
getIngredientById(id: Number): Promise<Ingredient | null>; getIngredientById(id: number): Promise<Ingredient | null>;
getIngredientByLetter(id: String): Promise<Ingredient[]>; getIngredientByLetter(id: string): Promise<Ingredient[]>;
getfilteredIngredient(prompt: String): Promise<Ingredient[]>; getfilteredIngredient(prompt: string): Promise<Ingredient[]>;
} }

@ -3,9 +3,7 @@ import IIngredientService from "./IIngredientService";
import axios from 'axios'; import axios from 'axios';
export default class IngredientService implements IIngredientService { export default class IngredientService implements IIngredientService {
private readonly API_URL = "http://localhost:3000/ingredients"; private readonly API_URL = "http://leftovers.alwaysdata.net/ingredients";
constructor() {}
async getAllIngredient(): Promise<Ingredient[]> { async getAllIngredient(): Promise<Ingredient[]> {
try { try {
@ -17,7 +15,7 @@ export default class IngredientService implements IIngredientService {
} }
async getIngredientById(id: Number): Promise<Ingredient | null>{ async getIngredientById(id: number): Promise<Ingredient | null>{
try { try {
const response = await axios.get(`${this.API_URL}/${id}`); const response = await axios.get(`${this.API_URL}/${id}`);
return response.data as Ingredient; return response.data as Ingredient;
@ -26,7 +24,7 @@ export default class IngredientService implements IIngredientService {
} }
} }
async getIngredientByLetter(letter: String): Promise<any>{ async getIngredientByLetter(letter: string): Promise<any>{
try { try {
const response = await axios.get(`${this.API_URL}/letter/${letter}`); const response = await axios.get(`${this.API_URL}/letter/${letter}`);
return response.data as Ingredient[]; return response.data as Ingredient[];
@ -35,13 +33,12 @@ export default class IngredientService implements IIngredientService {
} }
} }
async getfilteredIngredient(prompt: String): Promise<Ingredient[]> { async getfilteredIngredient(prompt: string): Promise<Ingredient[]> {
try { try {
const response = await axios.get(`${this.API_URL}/filter/${prompt}`); const response = await axios.get(`${this.API_URL}/filter/${prompt}`);
return response.data as Ingredient[]; return response.data as Ingredient[];
} catch (error) { } catch (error) {
throw new Error('Erreur lors de la récupération des ingrédients : ' + error.message); throw new Error('Erreur lors de la récupération des ingrédients : ' + error.message);
} }
return;
} }
} }

@ -2,5 +2,5 @@ import Recipes from "../../Models/Recipes";
export default interface IRecipesService { export default interface IRecipesService {
getAllRecipes(): Promise<Recipes[]>; getAllRecipes(): Promise<Recipes[]>;
getRecipeById(id: Number): Promise<Recipes | null>; getRecipeById(id: number): Promise<Recipes | null>;
} }

@ -3,9 +3,7 @@ import IRecipesService from "./IRecipesServices";
import Recipes from "../../Models/Recipes"; import Recipes from "../../Models/Recipes";
export default class RecipesService implements IRecipesService { export default class RecipesService implements IRecipesService {
private readonly API_URL = "http://localhost:3000/recipes"; private readonly API_URL = "http://leftovers.alwaysdata.net/recipes";
constructor() {}
async getAllRecipes(): Promise<Recipes[]> { async getAllRecipes(): Promise<Recipes[]> {
try { try {
@ -17,7 +15,7 @@ export default class RecipesService implements IRecipesService {
} }
async getRecipeById(id: Number): Promise<Recipes | null>{ async getRecipeById(id: number): Promise<Recipes | null>{
try { try {
const response = await axios.get(`${this.API_URL}/${id}`); const response = await axios.get(`${this.API_URL}/${id}`);
console.log(response); console.log(response);

@ -8,9 +8,9 @@
"scheme": "myapp", "scheme": "myapp",
"userInterfaceStyle": "automatic", "userInterfaceStyle": "automatic",
"splash": { "splash": {
"image": "./assets/images/splash.png", "image": "./assets/images/splashScreen.png",
"resizeMode": "contain", "resizeMode": "cover",
"backgroundColor": "#57BDCC" "backgroundColor": "#59BDCD"
}, },
"updates": { "updates": {
"fallbackToCacheTimeout": 0 "fallbackToCacheTimeout": 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

@ -1,5 +1,6 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet, Pressable, Text, View} from 'react-native'; import {StyleSheet, Pressable, Text, View} from 'react-native';
import ColorContext from '../theme/ColorContext';
interface CustomButtonProps { interface CustomButtonProps {
@ -7,6 +8,34 @@ interface CustomButtonProps {
} }
export default function CustomButton(props: CustomButtonProps) { export default function CustomButton(props: CustomButtonProps) {
const {colors} = useContext(ColorContext)
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width : 150,
height: 40,
borderRadius: 4,
backgroundColor: colors.cardBackground,
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: colors.cardElementBorder,
},
view: {
width : 145,
height: 35,
borderRadius: 4,
borderWidth: 1,
borderColor: colors.cardElementBorder,
alignItems: 'center',
justifyContent: 'center',
margin: "1%",
},
});
return ( return (
<Pressable style={styles.button}> <Pressable style={styles.button}>
<View style={styles.view}> <View style={styles.view}>
@ -15,30 +44,3 @@ export default function CustomButton(props: CustomButtonProps) {
</Pressable> </Pressable>
); );
} }
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width : 150,
height: 40,
borderRadius: 4,
backgroundColor: '#F2F0E4',
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: '#ACA279',
},
view: {
width : 145,
height: 35,
borderRadius: 4,
borderWidth: 1,
borderColor: '#ACA279',
alignItems: 'center',
justifyContent: 'center',
margin: "1%",
},
});

@ -1,10 +1,13 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import {StyleSheet,Pressable, Text, View} from 'react-native'; import {StyleSheet,Pressable, Text, View} from 'react-native';
import Separator from '../components/Separator';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
interface foodElementImageProps { interface FoodElementTextProps {
title : string title : string
mainColour: string
secondaryColour: string
} }
const componentHeight = 60; const componentHeight = 60;
@ -20,7 +23,7 @@ export default function FoodElementText(props : foodElementImageProps) {
justifyContent: 'center', justifyContent: 'center',
width: "80%", width: "80%",
borderRadius: 5, borderRadius: 5,
backgroundColor: colors.carrouselBackground, backgroundColor: props.mainColour ? props.mainColour : colors.ingredientBackground,
marginHorizontal: "3%", marginHorizontal: "3%",
}, },
text: { text: {
@ -41,7 +44,7 @@ export default function FoodElementText(props : foodElementImageProps) {
height: 50, height: 50,
borderRadius: 5, borderRadius: 5,
borderWidth: 2, borderWidth: 2,
borderColor: colors.cardDetail, borderColor: props.secondaryColour ? props.secondaryColour : colors.foodElementBorder,
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'space-between', justifyContent: 'space-between',
}, },

@ -1,15 +1,42 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet,Pressable, Text, View, Image} from 'react-native'; import {StyleSheet,Pressable, Text, View} from 'react-native';
import Separator from '../components/Separator'; import ColorContext from '../theme/ColorContext';
interface FoodElementTextSimpleProps {
interface foodElementTextProps {
title: string title: string
} }
export default function FoodElementTextSimple(props: FoodElementTextSimpleProps) {
const {colors} = useContext(ColorContext)
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width: "80%",
borderRadius: 5,
backgroundColor: colors.ingredientBackground,
},
text: {
fontSize: 10,
fontWeight: 'bold',
padding : "2%",
color: colors.cardDetail,
},
view: {
alignItems: 'flex-start',
justifyContent: 'center',
},
container: {
width: "100%",
borderRadius: 5,
borderWidth: 1,
borderColor: colors.foodElementBorder,
flexDirection: 'column',
justifyContent: 'center',
},
});
export default function FoodElementTextSimple(props: foodElementTextProps) {
return ( return (
<Pressable style={styles.button}> <Pressable style={styles.button}>
<View style={styles.container}> <View style={styles.container}>
@ -20,31 +47,3 @@ export default function FoodElementTextSimple(props: foodElementTextProps) {
</Pressable> </Pressable>
); );
} }
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width: "80%",
borderRadius: 5,
backgroundColor: '#E3DEC9',
},
text: {
fontSize: 10,
fontWeight: 'bold',
padding : "2%",
color: 'black',
},
view: {
alignItems: 'flex-start',
justifyContent: 'center',
},
container: {
width: "100%",
borderRadius: 5,
borderWidth: 1,
borderColor: '#3F3C42',
flexDirection: 'column',
justifyContent: 'center',
},
});

@ -6,6 +6,8 @@ import ColorContext from '../theme/ColorContext';
type ListProps = { type ListProps = {
title: string title: string
content : string[] content : string[]
val : string[]
setSelected: any;
} }
export default function ListSelect(props: ListProps) { export default function ListSelect(props: ListProps) {
@ -74,13 +76,16 @@ export default function ListSelect(props: ListProps) {
}, },
badgesText: { badgesText: {
fontSize: 15, fontSize: 15,
color: colors.cardElementText, color: colors.badgeText,
}, },
box: {
borderColor: "#3F3C42"
}
}); });
return ( return (
<MultipleSelectList <MultipleSelectList
setSelected={(val) => setSelected(val)} setSelected={(val) => props.setSelected(val)}
data={props.content} data={props.content}
save="value" save="value"
search={false} search={false}
@ -92,8 +97,10 @@ export default function ListSelect(props: ListProps) {
dropdownTextStyles={styles.itemText} dropdownTextStyles={styles.itemText}
badgeStyles={styles.badges} badgeStyles={styles.badges}
badgeTextStyles={styles.badgesText} badgeTextStyles={styles.badgesText}
checkBoxStyles={styles.box}
notFoundText="All Diets Already Selected" notFoundText="All Diets Already Selected"
placeholder={props.title} placeholder={props.title}
labelStyles={styles.title}
label={props.title}/> label={props.title}/>
); );
} }

@ -1,6 +1,5 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { StyleSheet, Image } from 'react-native'; import { StyleSheet, Image } from 'react-native';
import { MultipleSelectList } from 'react-native-dropdown-select-list' import { MultipleSelectList } from 'react-native-dropdown-select-list'
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
@ -60,6 +59,7 @@ export default function ListWithoutSelect(props: ListProps) {
width: "100%", width: "100%",
minWidth: 250, minWidth: 250,
maxWidth: 250, maxWidth: 250,
backgroundColor: colors.cardElementBackground,
}, },
itemText: { itemText: {
fontSize: 13, fontSize: 13,
@ -73,11 +73,13 @@ export default function ListWithoutSelect(props: ListProps) {
box: { box: {
borderWidth: 0, borderWidth: 0,
flex: 0, flex: 0,
backgroundColor: colors.cardElementBackground,
} }
}); });
return ( return (
<MultipleSelectList <MultipleSelectList
setSelected={(val) => setSelected(val)}
data={props.content} data={props.content}
save="value" save="value"
search={false} search={false}
@ -86,8 +88,11 @@ export default function ListWithoutSelect(props: ListProps) {
inputStyles={styles.title} inputStyles={styles.title}
dropdownStyles={styles.itemList} dropdownStyles={styles.itemList}
dropdownItemStyles={styles.itemCell} dropdownItemStyles={styles.itemCell}
disabledItemStyles={styles.itemCell}
dropdownTextStyles={styles.itemText} dropdownTextStyles={styles.itemText}
disabledTextStyles={styles.itemText}
checkBoxStyles={styles.box} checkBoxStyles={styles.box}
disabledCheckBoxStyles={styles.box}
notFoundText="None" notFoundText="None"
placeholder={props.title} placeholder={props.title}
label={props.title}/> label={props.title}/>

@ -1,5 +1,6 @@
import React from 'react'; import React, {useContext} from 'react';
import { Appbar } from 'react-native-paper'; import { Appbar } from 'react-native-paper';
import ColorContext from '../theme/ColorContext';
interface ParameterTopBarProps{ interface ParameterTopBarProps{
onEventIngredient: () => void onEventIngredient: () => void
@ -10,8 +11,10 @@ interface ParameterTopBarProps{
export default function ParameterTopBar(props : ParameterTopBarProps) { export default function ParameterTopBar(props : ParameterTopBarProps) {
const {colors} = useContext(ColorContext)
return ( return (
<Appbar.Header style={{backgroundColor: '#F2F0E4', height: "10%", justifyContent: "center", borderTopLeftRadius: 20, borderTopRightRadius: 20,}}> <Appbar.Header style={{backgroundColor: colors.cardBackground, height: 50, justifyContent: "center", borderTopLeftRadius: 20, borderTopRightRadius: 20}}>
<Appbar.Action icon="magnify" onPress={props.onEventIngredient} color={props.colorIngredients}/> <Appbar.Action icon="magnify" onPress={props.onEventIngredient} color={props.colorIngredients}/>
<Appbar.Action icon="dots-vertical" onPress={props.onEventFilter} color={props.colorFilters}/> <Appbar.Action icon="dots-vertical" onPress={props.onEventFilter} color={props.colorFilters}/>
</Appbar.Header> </Appbar.Header>

@ -1,16 +1,17 @@
import {React, useState} from 'react'; import React, {useContext, useState} from 'react';
import {StyleSheet, Text, TextInput, View, Image, Pressable} from 'react-native'; import {StyleSheet, Text, View, Image, Pressable} from 'react-native';
import ValidateButton from './ValidateButton';
import ListWithoutSelect from './ListWithoutSelect'; import ListWithoutSelect from './ListWithoutSelect';
import ColorContext from '../theme/ColorContext';
type ProfileProps = { type ProfileProps = {
name: string name: string
avatar: string avatar: string
diets: list<string> diets: {value: string}[]
allergies: list<string> allergies: {value: string}[]
} }
export default function ProfileDelete(props: ProfileProps) { export default function ProfileDelete(props: ProfileProps) {
const {colors} = useContext(ColorContext)
const [display, setDisplay] = useState("flex") const [display, setDisplay] = useState("flex")
const changeListVisibility = () => { const changeListVisibility = () => {
if (display == "none"){ if (display == "none"){
@ -32,6 +33,71 @@ export default function ProfileDelete(props: ProfileProps) {
imageSource = require('../assets/images/logo.png') imageSource = require('../assets/images/logo.png')
} }
const styles = StyleSheet.create({
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15,
backgroundColor: colors.cardBackground,
padding: "3%",
marginHorizontal: "3%",
height: "100%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
pseudoBar: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
width: "100%",
marginHorizontal: "3%",
marginBottom: "3%",
},
avatar: {
padding: "5%",
resizeMode: 'contain',
borderWidth: 2,
borderColor: colors.cardElementBorder,
borderRadius: 45,
height: "100%",
flex: 0.03,
},
text: {
flex: 1,
fontSize: 20,
color: colors.cardElementBorder,
alignItems: 'center',
textAlign: 'left',
marginLeft: "10%",
padding: "2%",
height: "100%",
},
filterBar: {
flexDirection: "row",
width: "90%",
paddingTop: "3%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: colors.cardElementBorder,
flex: 1,
padding: "2%",
paddingLeft: 0,
paddingBottom: 0,
},
arrow: {
height: "100%",
resizeMode: 'contain',
tintColor: colors.cardDetail,
flex: 0.1,
},
});
return ( return (
<View style={styles.background}> <View style={styles.background}>
<View style={styles.pseudoBar}> <View style={styles.pseudoBar}>
@ -52,66 +118,3 @@ export default function ProfileDelete(props: ProfileProps) {
</View> </View>
); );
} }
const styles = StyleSheet.create({
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15,
backgroundColor: '#F2F0E4',
padding: "3%",
marginHorizontal: "3%",
height: "100%",
},
pseudoBar: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
width: "100%",
marginHorizontal: "3%",
marginBottom: "3%",
},
avatar: {
padding: "5%",
resizeMode: 'contain',
borderWidth: 2,
borderColor: "#ACA279",
borderRadius: 45,
height: "100%",
flex: 0.03,
},
text: {
flex: 1,
fontSize: 20,
color: '#ACA279',
alignItems: 'center',
textAlign: 'left',
marginLeft: "10%",
padding: "2%",
height: "100%",
},
filterBar: {
flexDirection: "row",
width: "90%",
paddingTop: "3%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: '#ACA279',
flex: 1,
padding: "2%",
paddingLeft: 0,
paddingBottom: 0,
},
arrow: {
height: "100%",
resizeMode: 'contain',
tintColor: "#3F3C42",
flex: 0.1,
},
});

@ -1,6 +1,5 @@
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
import { StyleSheet, Text, View, Image, Pressable } from 'react-native'; import { StyleSheet, Text, View, Image, Pressable } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import ListWithoutSelect from './ListWithoutSelect'; import ListWithoutSelect from './ListWithoutSelect';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
@ -10,6 +9,7 @@ type ProfileProps = {
avatar: string avatar: string
diets: string[] diets: string[]
allergies: string[] allergies: string[]
onModification: () => void
onDeleteProfile: () => void onDeleteProfile: () => void
} }
@ -47,6 +47,8 @@ export default function ProfileDetails(props) {
backgroundColor: colors.cardBackground, backgroundColor: colors.cardBackground,
padding: "3%", padding: "3%",
marginHorizontal: "3%", marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
}, },
pseudoBar: { pseudoBar: {
@ -78,10 +80,10 @@ export default function ProfileDetails(props) {
}, },
modify: { modify: {
height: "100%", height: "100%",
width: "100%",
tintColor: colors.cardElementBorder, tintColor: colors.cardElementBorder,
resizeMode: 'contain', resizeMode: 'contain',
flex: 0.1, flex: 1,
marginLeft: "3%",
}, },
delete: { delete: {
height: "100%", height: "100%",
@ -128,7 +130,9 @@ export default function ProfileDetails(props) {
<View style={styles.pseudoBar}> <View style={styles.pseudoBar}>
<Image source={imageSource} style={styles.avatar}></Image> <Image source={imageSource} style={styles.avatar}></Image>
<Text style={styles.text}>{props.name}</Text> <Text style={styles.text}>{props.name}</Text>
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image> <Pressable onPress={props.onModification} style={{flex: 0.1, marginRight: "1%",}}>
<Image source={require("../assets/images/modify.png")} style={styles.modify}></Image>
</Pressable>
<Pressable onPress={props.onDeleteProfile} style={{flex: 0.1, marginLeft: "1%",}}> <Pressable onPress={props.onDeleteProfile} style={{flex: 0.1, marginLeft: "1%",}}>
<Image source={require("../assets/images/delete.png")} style={styles.delete}></Image> <Image source={require("../assets/images/delete.png")} style={styles.delete}></Image>
</Pressable> </Pressable>
@ -136,7 +140,7 @@ export default function ProfileDetails(props) {
<Pressable onPress={changeListVisibility} style={{height: "5%", marginTop: "6%", flex: 1, marginBottom: "3%"}}> <Pressable onPress={changeListVisibility} style={{height: "5%", marginTop: "6%", flex: 1, marginBottom: "3%"}}>
<View style={styles.filterBar}> <View style={styles.filterBar}>
<Text style={styles.filters}>Filters</Text> <Text style={styles.filters}>Filters</Text>
<Text style={styles.nbSelected}>{props.diets.length} selected</Text> <Text style={styles.nbSelected}>{props.diets.length} diets selected</Text>
<Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image> <Image source={require("../assets/images/arrow.png")} style={styles.arrow}></Image>
</View> </View>
</Pressable> </Pressable>

@ -33,18 +33,15 @@ export default function ProfileElement(props : Profile) {
else{ else{
setSeparator("none") setSeparator("none")
} }
console.log(waiting, separator, props.name)
} }
let imageSource let imageSource
if (props.avatar == "plus.png"){ if(props.avatar == null){
imageSource = require('../assets/images/plus.png') console.log("NUUUULLLLLE" + props.avatar)
}
else if (props.avatar == "plus_small.png"){
imageSource = require('../assets/images/plus_small.png')
} }
else{ else{
imageSource = require('../assets/images/logo.png') imageSource = { uri: props.avatar };
console.log("MAAARCHHEEE" + props.avatar)
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -96,12 +93,12 @@ export default function ProfileElement(props : Profile) {
waiting: { waiting: {
borderWidth: 1, borderWidth: 1,
borderRadius: 20, borderRadius: 20,
borderColor: "#ACA279", borderColor: colors.cardElementBorder,
padding: "1%", padding: "1%",
}, },
textWaiting: { textWaiting: {
fontSize: 10, fontSize: 10,
color: "#ACA279", color: colors.cardElementBorder,
}, },
}); });

@ -9,8 +9,8 @@ import ColorContext from '../theme/ColorContext';
type ProfileProps = { type ProfileProps = {
name: string name: string
avatar: string avatar: string
diets: string[] diets: {value: string}[]
allergies: string[] allergies: {value: string}[]
} }
export default function ProfileModification(props: ProfileProps) { export default function ProfileModification(props: ProfileProps) {
@ -37,6 +37,8 @@ export default function ProfileModification(props: ProfileProps) {
backgroundColor: colors.cardBackground, backgroundColor: colors.cardBackground,
padding: "3%", padding: "3%",
marginHorizontal: "3%", marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
}, },
pseudoBar: { pseudoBar: {
@ -51,18 +53,18 @@ export default function ProfileModification(props: ProfileProps) {
padding: "5%", padding: "5%",
resizeMode: 'contain', resizeMode: 'contain',
borderWidth: 2, borderWidth: 2,
borderColor: colors.cardTitle, borderColor: colors.cardElementBorder,
borderRadius: 45, borderRadius: 45,
height: "100%", height: "100%",
flex: 0.04, flex: 0.04,
}, },
textInput: { textInput: {
fontSize: 15, fontSize: 15,
color: colors.cardTitle, color: colors.cardDetail,
borderRadius: 10, borderRadius: 10,
borderWidth: 2, borderWidth: 2,
borderStyle: 'dashed', borderStyle: 'dashed',
borderColor: colors.cardTitle, borderColor: colors.cardElementBorder,
alignItems: 'center', alignItems: 'center',
textAlign: 'left', textAlign: 'left',
flex: 0.8, flex: 0.8,
@ -71,7 +73,7 @@ export default function ProfileModification(props: ProfileProps) {
}, },
modify: { modify: {
height: "100%", height: "100%",
tintColor: colors.cardTitle, tintColor: colors.cardElementBorder,
resizeMode: 'contain', resizeMode: 'contain',
flex: 0.1, flex: 0.1,
marginLeft: "3%", marginLeft: "3%",
@ -87,14 +89,9 @@ export default function ProfileModification(props: ProfileProps) {
}, },
filters: { filters: {
fontSize: 20, fontSize: 20,
color: colors.cardTitle, color: colors.cardElementBorder,
flex: 1, flex: 1,
}, },
nbSelected: {
fontSize: 11,
color: colors.cardDetail,
textAlign: "right",
}
}); });
return ( return (
@ -106,7 +103,6 @@ export default function ProfileModification(props: ProfileProps) {
</View> </View>
<View style={styles.filterBar}> <View style={styles.filterBar}>
<Text style={styles.filters}>Filters</Text> <Text style={styles.filters}>Filters</Text>
<Text style={styles.nbSelected}>3 selected</Text>
</View> </View>
<ListSelect title="Diets" content={props.diets}></ListSelect> <ListSelect title="Diets" content={props.diets}></ListSelect>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>

@ -1,24 +1,86 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet,Pressable, Text, View, Image, SafeAreaView, ScrollView} from 'react-native'; import {StyleSheet, Pressable, Text, View, Image, ScrollView} from 'react-native';
import brochette from '../assets/images/brochette.png'; import brochette from '../assets/images/brochette.png';
import Union_left from '../assets/images/Union_left.png'; import Union_left from '../assets/images/Union_left.png';
import Union_right from '../assets/images/Union_right.png'; import Union_right from '../assets/images/Union_right.png';
import background from '../assets/images/Background.png'; import background from '../assets/images/Background.png';
import ColorContext from '../theme/ColorContext';
interface recipeElementProps { interface RecipeElementProps {
number: string number: string
title: string title: string
textList: string[] textList: {title: string}[]
description: string description: string
duration: string
navigateDetails: () => void
} }
export default function RecipeElement(props: recipeElementProps) { export default function RecipeElement(props: RecipeElementProps) {
const {colors} = useContext(ColorContext)
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width: 300,
height: "90%",
borderRadius: 40,
backgroundColor: colors.recipeElementBackground,
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: '#6F6532',
marginTop: "4%",
},
smallText: {
fontSize: 12,
color: '#71662A',
textAlign: "center",
margin : "2%",
zIndex: 2,
},
duration:{
fontSize: 12,
color: '#F2F0E4',
textAlign: "center",
margin : "2%",
zIndex: 2,
},
title:{
fontSize: 18,
fontWeight: 'bold',
color: '#524B1A',
},
view: {
width : "95%",
height: "96.5%",
borderRadius: 40,
borderWidth: 2,
padding: "5%",
borderColor: '#6F6532',
alignItems: 'center',
justifyContent: "center",
},
horizontalAlignment: {
display: "flex",
flexDirection : 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginTop : "2%",
flexWrap: 'wrap',
},
scrollViewContainer: {
flex: 1,
},
});
return ( return (
<Pressable style={styles.button}> <Pressable style={styles.button} onPress={props.navigateDetails}>
<View style={styles.view}> <View style={styles.view}>
<Text style={styles.text}>{props.number}</Text> <Text style={styles.text}>{props.number}</Text>
<Text style={styles.title}>{props.title}</Text> <Text style={styles.title}>{props.title}</Text>
<Image source={props.image ? props.image : brochette} style={{width: 100, resizeMode: "contain"}}/> <Image source={brochette} style={{width: 100, resizeMode: "contain"}}/>
<View style={styles.horizontalAlignment}> <View style={styles.horizontalAlignment}>
<Image source={Union_left} style={{width: "25%", marginRight: "3%", resizeMode: "contain"}} /> <Image source={Union_left} style={{width: "25%", marginRight: "3%", resizeMode: "contain"}} />
<Text style={styles.text}>Ingredients</Text> <Text style={styles.text}>Ingredients</Text>
@ -39,58 +101,9 @@ export default function RecipeElement(props: recipeElementProps) {
<Text style={styles.smallText}>{props.description}</Text> <Text style={styles.smallText}>{props.description}</Text>
</ScrollView> </ScrollView>
</View> </View>
<Image source={background} style={{width: "80%", resizeMode: "contain"}}></Image> <Image source={background} style={{width: "80%", resizeMode: "contain", position: "absolute", zIndex: 1, top: "97.5%"}}></Image>
<Text style={styles.duration}>{props.duration}</Text>
</View> </View>
</Pressable> </Pressable>
); );
} }
const styles = StyleSheet.create({
button: {
alignItems: 'center',
justifyContent: 'center',
width: 300,
height: "90%",
borderRadius: 40,
backgroundColor: '#E3DEC9',
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: '#756C28',
marginTop: "4%",
},
smallText: {
fontSize: 12,
color: '#71662A',
textAlign: "center",
margin : "2%"
},
title:{
fontSize: 18,
fontWeight: 'bold',
color: '#524B1A',
},
view: {
width : "95%",
height: "96.5%",
borderRadius: 40,
borderWidth: 2,
padding: "5%",
borderColor: '#73692A',
alignItems: 'center',
justifyContent: "center",
},
horizontalAlignment: {
display: "flex",
flexDirection : 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginTop : "2%",
flexWrap: 'wrap',
},
scrollViewContainer: {
flex: 1,
},
});

@ -1,17 +1,17 @@
import React from 'react'; import React from 'react';
import {StyleSheet,Pressable, Text, View, Image} from 'react-native'; import {StyleSheet, Text, View, Image} from 'react-native';
import brochette from '../assets/images/brochette.png'; import brochette from '../assets/images/brochette.png';
import background from '../assets/images/Background.png'; import background from '../assets/images/Background.png';
interface recipeElementReduceProps { interface RecipeElementReduceProps {
number : number number : number
title : string title : string
image : string | null image : string | null
duration : string duration : string
} }
export default function RecipeElementReduce(props: recipeElementReduceProps) { export default function RecipeElementReduce(props: RecipeElementReduceProps) {
return ( return (
<View style={styles.button}> <View style={styles.button}>
<View style={styles.view}> <View style={styles.view}>

@ -1,17 +1,19 @@
import React, { useState } from 'react'; import React, { useState, useContext } from 'react';
import {View, StyleSheet, Pressable, Image, Text} from 'react-native'; import {View, StyleSheet, Pressable, Image, Text} from 'react-native';
import bracketLeft from '../assets/images/angle_bracket_left.png'; import bracketLeft from '../assets/images/angle_bracket_left.png';
import bracketRight from '../assets/images/angle_bracket_right.png'; import bracketRight from '../assets/images/angle_bracket_right.png';
import parameter from '../assets/images/parameter.png'; import parameter from '../assets/images/parameter.png';
import FoodElementText from './FoodElementText'; import FoodElementText from './FoodElementText';
import ColorContext from '../theme/ColorContext';
interface SelectedIngredientProps { interface SelectedIngredientProps {
ingredientList: string[] ingredientList: {title: string}[]
onEvent: () => void onEvent: () => void
} }
export default function SelectedIngredient(props: SelectedIngredientProps) { export default function SelectedIngredient(props: SelectedIngredientProps) {
const [cpt, setCpt] = useState(0); const [cpt, setCpt] = useState(0);
const {colors} = useContext(ColorContext)
const decreaseCounter = () => { const decreaseCounter = () => {
if(cpt > 0){ if(cpt > 0){
@ -30,50 +32,51 @@ export default function SelectedIngredient(props: SelectedIngredientProps) {
} }
}; };
const styles = StyleSheet.create({
view: {
width: "90%",
paddingBottom: "5%",
borderRadius: 15,
borderWidth: 1,
borderColor: colors.blocBorder,
backgroundColor: colors.buttonBackground,
alignItems: "center",
justifyContent: "center",
},
horizontalAlignment: {
width: "90%",
flexDirection: 'row',
justifyContent: 'space-evenly',
alignItems: 'center',
marginTop: "3%",
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: colors.cardDetail,
flex: 1,
marginLeft: "8%",
},
});
return ( return (
<View style={styles.view}> <View style={styles.view}>
<View style={styles.horizontalAlignment}> <View style={styles.horizontalAlignment}>
<Text style={styles.text}>Selected ingredients</Text> <Text style={styles.text}>Selected ingredients</Text>
<Pressable onPress={props.onEvent}> <Pressable onPress={props.onEvent}>
<Image source={parameter} style={{tintColor: "#3F3C42", resizeMode: "contain", flex: 1, marginRight: "8%"}}/> <Image source={parameter} style={{tintColor: colors.cardDetail, resizeMode: "contain", flex: 1, marginRight: "8%"}}/>
</Pressable> </Pressable>
</View> </View>
<View style={styles.horizontalAlignment}> <View style={styles.horizontalAlignment}>
<Pressable onPress={decreaseCounter}> <Pressable onPress={decreaseCounter}>
<Image source={bracketLeft} style={{width: 40, height: 40, tintColor: "#3F3C42", resizeMode: "contain"}}/> <Image source={bracketLeft} style={{width: 40, height: 40, tintColor: colors.cardDetail, resizeMode: "contain"}}/>
</Pressable> </Pressable>
<FoodElementText title={props.ingredientList[cpt].title}/> <FoodElementText title={props.ingredientList[cpt].title}/>
<Pressable onPress={increaseCounter}> <Pressable onPress={increaseCounter}>
<Image source={bracketRight} style={{width: 40, height: 40, tintColor: "#3F3C42", resizeMode: "contain"}}/> <Image source={bracketRight} style={{width: 40, height: 40, tintColor: colors.cardDetail, resizeMode: "contain"}}/>
</Pressable> </Pressable>
</View> </View>
</View> </View>
); );
} }
const styles = StyleSheet.create({
view: {
width: "90%",
paddingBottom: "5%",
borderRadius: 15,
borderColor: '#3F3C42',
backgroundColor: '#E3DEC9',
alignItems: "center",
justifyContent: "center",
},
horizontalAlignment: {
width: "90%",
flexDirection: 'row',
justifyContent: 'space-evenly',
alignItems: 'center',
marginTop: "3%",
},
text: {
fontSize: 15,
fontWeight: 'bold',
color: '#3F3C42',
flex: 1,
marginLeft: "8%",
},
});

@ -1,17 +1,20 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet, View} from 'react-native'; import {StyleSheet, View} from 'react-native';
import ColorContext from '../theme/ColorContext';
export default function Separator (){ export default function Separator (){
return <View style={styles.separator} />; const {colors } = useContext(ColorContext)
};
const styles = StyleSheet.create({ const styles = StyleSheet.create({
separator: { separator: {
width: "90%", width: "90%",
backgroundColor: '#3F3C42', backgroundColor: colors.cardDetail,
borderWidth : 1, borderWidth : 1,
marginLeft : "5%", marginLeft : "5%",
marginRight : "5%", marginRight : "5%",
}, borderColor: colors.cardDetail,
}); },
});
return <View style={styles.separator} />;
};

@ -83,6 +83,7 @@ export default function ValidateButton(props: ValidateButtonProps) {
<Text style={{ <Text style={{
fontSize: 15, fontSize: 15,
color: props.colour, color: props.colour,
fontWeight: "bold",
}}>{props.title}</Text> }}>{props.title}</Text>
</View> </View>
</Pressable> </Pressable>

@ -1,6 +1,5 @@
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
import { View, Text, TouchableOpacity, Image, Pressable } from 'react-native'; import { View, Text, TouchableOpacity, Image, Pressable, GestureResponderEvent, StyleSheet } from 'react-native';
import { GestureResponderEvent, StyleSheet } from 'react-native';
import { BlurView } from 'expo-blur'; import { BlurView } from 'expo-blur';
import ThemeContext from '../theme/ThemeContext'; import ThemeContext from '../theme/ThemeContext';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
@ -41,29 +40,26 @@ export default function BottomBar({ state, descriptors, navigation }) {
bottom: 0, bottom: 0,
right: 0, right: 0,
left: 0, left: 0,
height: 70, height: "8%",
backgroundColor: theme === 'dark' ? "#3F3C42" : "transparent" backgroundColor: theme === 'dark' ? "#3F3C42" : "transparent"
}, },
BottomBarBlurContainer: { BottomBarBlurContainer: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
alignContent: 'space-around', alignContent: 'space-around',
padding: 2,
borderBlockColor: theme === 'light' ? '#F2F0E4' : '#222222', borderBlockColor: theme === 'light' ? '#F2F0E4' : '#222222',
borderWidth: 3, borderWidth: 2,
borderLeftColor: theme === 'light'? '#F2F0E4' : '#222222', borderLeftColor: theme === 'light'? '#F2F0E4' : '#222222',
borderLeftWidth: 3,
borderRightColor: theme === 'light'? '#F2F0E4' : '#222222', borderRightColor: theme === 'light'? '#F2F0E4' : '#222222',
borderRightWidth: 3
}, },
BottomBarIcon: { BottomBarIcon: {
width: 35, width: 25,
height: 35 height: 25,
resizeMode: "contain",
}, },
BottomBarElementContainer: { BottomBarElementContainer: {
flexDirection: 'column', flexDirection: 'column',
alignItems: 'center', alignItems: 'center',
margin: 3
} }
}) })
@ -73,7 +69,7 @@ export default function BottomBar({ state, descriptors, navigation }) {
style={[StyleSheet.absoluteFill, styles.BottomBarBlurContainer]} style={[StyleSheet.absoluteFill, styles.BottomBarBlurContainer]}
tint='dark' tint='dark'
intensity={theme === 'light' ? 50 : 0} intensity={theme === 'light' ? 50 : 0}
> >
{state.routes.map((route, index) => { {state.routes.map((route, index) => {
const { options } = descriptors[route.key]; const { options } = descriptors[route.key];
const label = const label =
@ -86,7 +82,7 @@ export default function BottomBar({ state, descriptors, navigation }) {
let icon; let icon;
if (route.name === 'HOME') { if (route.name === 'HOME') {
icon = HomeIcon; icon = HomeIcon;
} else if (route.name === 'PROFILE') { } else if (route.name === 'PROFILES') {
icon = ProfileIcon; icon = ProfileIcon;
} else if (route.name === 'COOKING') { } else if (route.name === 'COOKING') {
icon = CookingIcon; icon = CookingIcon;
@ -115,19 +111,21 @@ export default function BottomBar({ state, descriptors, navigation }) {
onPress={onPress} onPress={onPress}
style={[styles.BottomBarElementContainer, { flex: 1 }]} style={[styles.BottomBarElementContainer, { flex: 1 }]}
key={route.name} key={route.name}
> >
<Image source={icon} style={[styles.BottomBarIcon, {tintColor: isFocused ? (theme === 'light' ? '#59BDCD': '#8DB4D9'): '#F2F0E4'}]} /> <Image source={icon} style={[styles.BottomBarIcon, {tintColor: isFocused ? (theme === 'light' ? '#59BDCD': '#8DB4D9'): '#F2F0E4'}]} />
<Text style={{ color: isFocused ? '#59BDCD' : '#F2F0E4' }}> <Text style={{ color: isFocused ? colors.textBottomBarFocussed : '#F2F0E4' }}>
{label} {label}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
); );
})} })}
<Pressable onPress={ onThemeButtonPress }> <Pressable onPress={ onThemeButtonPress } style={{paddingHorizontal: "7%"}}>
<View style={{alignItems: "center", justifyContent: "center"}}>
<Image source={iconThemeButton} style={[styles.BottomBarIcon, {tintColor: '#F2F0E4'}]} /> <Image source={iconThemeButton} style={[styles.BottomBarIcon, {tintColor: '#F2F0E4'}]} />
<Text style={{color: '#F2F0E4'}}> <Text style={{color: '#F2F0E4'}}>
{textThemeButton} {textThemeButton}
</Text> </Text>
</View>
</Pressable> </Pressable>
</BlurView> </BlurView>
</View> </View>

@ -1,16 +1,18 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import { Image, Text, StyleSheet } from 'react-native'; import { Image, StyleSheet } from 'react-native';
import { createNativeStackNavigator } from '@react-navigation/native-stack'; import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomePage from '../screens/HomePage'; import HomePage from '../screens/HomePage';
import Profiles from '../screens/Profiles'; import Profiles from '../screens/Profiles';
import CreateProfile from '../screens/CreateProfile';
import ModifyProfile from '../screens/ModifyProfile';
import ThemeContext from '../theme/ThemeContext';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
import { HeaderTitle } from './Utils'; import { HeaderTitle } from './Utils';
import appLogo from '../assets/images/logo.png'; import appLogo from '../assets/images/logo.png';
import IngredientSelection from '../screens/IngredientSelection';
import RecipeSuggestion from '../screens/RecipeSuggestion';
import FiltersSelection from '../screens/FiltersSelection';
import RecipeDetails from '../screens/RecipeDetails';
import ModifyProfile from '../screens/ModifyProfile';
const HomeStack = createNativeStackNavigator() const HomeStack = createNativeStackNavigator()
@ -57,6 +59,46 @@ export default function HomeStackScreen() {
) )
}} }}
/> />
<HomeStack.Screen
name='IngredientSelection'
component={IngredientSelection}
options={{
headerStyle: {backgroundColor: colors.cardBackground},
headerTitle: () => (
<HeaderTitle title='Ingredient Selection'/>
)
}}
/>
<HomeStack.Screen
name='RecipeSuggestion'
component={RecipeSuggestion}
options={{
headerStyle: {backgroundColor: colors.cardBackground},
headerTitle: () => (
<HeaderTitle title='Recipe Suggestion'/>
)
}}
/>
<HomeStack.Screen
name='FiltersSelection'
component={FiltersSelection}
options={{
headerStyle: {backgroundColor: colors.cardBackground},
headerTitle: () => (
<HeaderTitle title='Filters Selection'/>
)
}}
/>
<HomeStack.Screen
name='RecipeDetails'
component={RecipeDetails}
options={{
headerStyle: {backgroundColor: colors.cardBackground},
headerTitle: () => (
<HeaderTitle title='Recipe Details'/>
)
}}
/>
<HomeStack.Screen <HomeStack.Screen
name='ProfileModification' name='ProfileModification'
component={ModifyProfile} component={ModifyProfile}

@ -34,7 +34,9 @@ export default function ProfilesStackScreen({ navigation }) {
} }
}) })
const _handleSearch = () => console.log('Searching'); const _handleSearch = () => {
console.log('Searching');
}
const _handleHeaderAdd = () => navigation.navigate('ProfileCreation'); const _handleHeaderAdd = () => navigation.navigate('ProfileCreation');
return ( return (

@ -17,6 +17,7 @@
"axios": "^1.6.2", "axios": "^1.6.2",
"expo": "~49.0.15", "expo": "~49.0.15",
"expo-blur": "^12.4.1", "expo-blur": "^12.4.1",
"expo-image-picker": "~14.3.2",
"expo-linear-gradient": "~12.3.0", "expo-linear-gradient": "~12.3.0",
"expo-splash-screen": "~0.20.5", "expo-splash-screen": "~0.20.5",
"expo-status-bar": "~1.6.0", "expo-status-bar": "~1.6.0",
@ -28,6 +29,7 @@
"react-native-safe-area-context": "^4.6.3", "react-native-safe-area-context": "^4.6.3",
"react-native-screens": "^3.22.0", "react-native-screens": "^3.22.0",
"react-native-splash-screen": "^3.3.0", "react-native-splash-screen": "^3.3.0",
"react-native-virtualized-view": "^1.0.0",
"react-native-web": "~0.19.6", "react-native-web": "~0.19.6",
"typescript": "^5.1.3" "typescript": "^5.1.3"
}, },
@ -9281,6 +9283,25 @@
"expo": "*" "expo": "*"
} }
}, },
"node_modules/expo-image-loader": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.3.0.tgz",
"integrity": "sha512-2kqJIO+oYM8J3GbvTUHLqTSpt1dLpOn/X0eB4U4RTuzz/faj8l/TyQELsMBLlGAkweNUuG9LqznbaBz+WuSFEw==",
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-image-picker": {
"version": "14.3.2",
"resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-14.3.2.tgz",
"integrity": "sha512-xr/YeQMIYheXecWP033F2SPwpBlBR5xVCx7YSfSCTH8Y9pw7Z886agqKGbS9QBVGlzJ5qecJktZ6ASSzeslDVg==",
"dependencies": {
"expo-image-loader": "~4.3.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-keep-awake": { "node_modules/expo-keep-awake": {
"version": "12.3.0", "version": "12.3.0",
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz",
@ -15215,6 +15236,15 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/react-native-virtualized-view": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-virtualized-view/-/react-native-virtualized-view-1.0.0.tgz",
"integrity": "sha512-7YyFMMkNzJ787/giGkKcm0JEx0IcLEE/XHREGz2I4K1RISQGFjEDe6iWsapOnHSR/e1vhebZJ8VmqhSpg5YPzg==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-web": { "node_modules/react-native-web": {
"version": "0.19.9", "version": "0.19.9",
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.9.tgz", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.9.tgz",
@ -24631,6 +24661,20 @@
"fontfaceobserver": "^2.1.0" "fontfaceobserver": "^2.1.0"
} }
}, },
"expo-image-loader": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.3.0.tgz",
"integrity": "sha512-2kqJIO+oYM8J3GbvTUHLqTSpt1dLpOn/X0eB4U4RTuzz/faj8l/TyQELsMBLlGAkweNUuG9LqznbaBz+WuSFEw==",
"requires": {}
},
"expo-image-picker": {
"version": "14.3.2",
"resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-14.3.2.tgz",
"integrity": "sha512-xr/YeQMIYheXecWP033F2SPwpBlBR5xVCx7YSfSCTH8Y9pw7Z886agqKGbS9QBVGlzJ5qecJktZ6ASSzeslDVg==",
"requires": {
"expo-image-loader": "~4.3.0"
}
},
"expo-keep-awake": { "expo-keep-awake": {
"version": "12.3.0", "version": "12.3.0",
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz", "resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-12.3.0.tgz",
@ -28947,6 +28991,12 @@
} }
} }
}, },
"react-native-virtualized-view": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/react-native-virtualized-view/-/react-native-virtualized-view-1.0.0.tgz",
"integrity": "sha512-7YyFMMkNzJ787/giGkKcm0JEx0IcLEE/XHREGz2I4K1RISQGFjEDe6iWsapOnHSR/e1vhebZJ8VmqhSpg5YPzg==",
"requires": {}
},
"react-native-web": { "react-native-web": {
"version": "0.19.9", "version": "0.19.9",
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.9.tgz", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.19.9.tgz",

@ -29,8 +29,10 @@
"react-native-safe-area-context": "^4.6.3", "react-native-safe-area-context": "^4.6.3",
"react-native-screens": "^3.22.0", "react-native-screens": "^3.22.0",
"react-native-splash-screen": "^3.3.0", "react-native-splash-screen": "^3.3.0",
"react-native-virtualized-view": "^1.0.0",
"react-native-web": "~0.19.6", "react-native-web": "~0.19.6",
"typescript": "^5.1.3" "typescript": "^5.1.3",
"expo-image-picker": "~14.3.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0" "@babel/core": "^7.20.0"

@ -1,32 +1,81 @@
import React, { useContext } from 'react'; import React, { useContext, useState } from 'react';
import {StyleSheet, View, ScrollView, useWindowDimensions} from 'react-native'; import {StyleSheet, View, ScrollView, useWindowDimensions, TextInput, Image, Text, NativeEventEmitter, Pressable} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import ProfileModification from '../components/ProfileModification';
import ValidateButton from '../components/ValidateButton'; import ValidateButton from '../components/ValidateButton';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
import ListWithoutSelect from '../components/ListWithoutSelect';
import ListSelect from '../components/ListSelect';
import AsyncStorage from '@react-native-async-storage/async-storage';
import EventEmitter from './EventEmitter';
import * as ImagePicker from 'expo-image-picker';
export default function CreateProfile(props) { export default function CreateProfile(props) {
const colors = useContext(ColorContext).colors const colors = useContext(ColorContext).colors
const all = [] const all = []
const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}] const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
const [name, onChangeName] = useState();
const [avatar, setAvatar] = useState<string>('');
const [selectedDiets, setSelectedDiets] = useState([]);
const handleSelectedDiets = (selectedValues) => {
setSelectedDiets(selectedValues);
};
const pickImage = async () => {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.canceled) {
setAvatar(result.assets[0].uri);
}
};
let imageSource
if (props.avatar == "plus.png"){
imageSource = {uri: avatar}
}
else if (props.avatar == "plus_small.png"){
imageSource = {uri: avatar}
}
else{
imageSource = {uri: avatar}
}
const handleCreateProfile = async () => {
try {
// Ton code pour récupérer les profils existants et ajouter un nouveau profil
const newProfile = {
name: name,
avatar: avatar,
diets: selectedDiets,
allergies: all,
};
// Mettre à jour AsyncStorage avec le nouveau profil
let existingProfiles = await AsyncStorage.getItem('profiles');
existingProfiles = existingProfiles ? JSON.parse(existingProfiles) : [];
const updatedProfiles = [...existingProfiles, newProfile];
await AsyncStorage.setItem('profiles', JSON.stringify(updatedProfiles));
EventEmitter.emit('profileAdded');
console.log('Profil créé :', newProfile);
props.navigation.goBack();
const handleCreateProfile = () => { alert('Profil créé !');
const profileData = { } catch (error) {
name: "Nom du profil", // Remplacez par le nom du profil console.error('Erreur lors de la création du profil :', error);
avatar: "Lien de l'avatar", // Remplacez par le lien de l'avatar }
diets: die.map(item => item.value), // Liste des régimes
allergies: all, // Liste des allergies
};
localStorage.setItem('profile', JSON.stringify(profileData));
console.log("Profil créé :", profileData);
// Redirection vers la page précédente avec un message de confirmation
props.navigation.goBack();
// Affichage d'un message
alert("Profil créé !");
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -36,7 +85,74 @@ export default function CreateProfile(props) {
flex: 1, flex: 1,
padding: "2%", padding: "2%",
paddingTop: 0, paddingTop: 0,
},background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 15,
backgroundColor: colors.cardBackground,
padding: "3%",
marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
pseudoBar: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
width: "100%",
marginHorizontal: "3%",
marginBottom: "3%",
},
avatar: {
padding: "5%",
resizeMode: 'contain',
borderWidth: 2,
borderColor: colors.cardElementBorder,
borderRadius: 45,
height: "100%",
flex: 0.04,
},
textInput: {
fontSize: 15,
color: colors.cardTitle,
borderRadius: 10,
borderWidth: 2,
borderStyle: 'dashed',
borderColor: colors.cardElementBorder,
alignItems: 'center',
textAlign: 'left',
flex: 0.8,
marginLeft: "7%",
padding: "2%",
},
modify: {
height: "100%",
tintColor: colors.cardElementBorder,
resizeMode: 'contain',
flex: 0.1,
marginLeft: "3%",
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: colors.cardElementBorder,
flex: 1,
}, },
nbSelected: {
fontSize: 11,
color: colors.cardDetail,
textAlign: "right",
}
}); });
return ( return (
@ -44,9 +160,24 @@ export default function CreateProfile(props) {
<ScrollView> <ScrollView>
<LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<ProfileModification name="" avatar="plus_small.png" diets={die} allergies={all}></ProfileModification> <View style={styles.background}>
<View style={styles.pseudoBar}>
<Pressable onPress={pickImage}>
<Image source={imageSource} style={styles.avatar}></Image>
</Pressable>
<TextInput style={styles.textInput} value={name} onChangeText={onChangeName} placeholder="Name"></TextInput>
</View>
<View style={styles.filterBar}>
<Text style={styles.filters}>Filters</Text>
<Text style={styles.nbSelected}>"0 diets selected</Text>
</View>
<ListSelect title="Diets" content={die} setSelected={handleSelectedDiets}></ListSelect>
<View style={{marginTop: "6%"}}/>
<ListWithoutSelect title="Allergies" content={all}></ListWithoutSelect>
<View style={{marginTop: "3%"}}/>
</View>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ValidateButton title="Create Profile" image="plus.png" colour={colors.cardTitle} backColour={colors.cardBackground} todo={handleCreateProfile}></ValidateButton> <ValidateButton title="Create Profile" image="plus.png" colour={colors.buttonMain} backColour={colors.cardBackground} todo={handleCreateProfile}></ValidateButton>
<View style={{marginTop: "20%"}}/> <View style={{marginTop: "20%"}}/>
</LinearGradient> </LinearGradient>
</ScrollView> </ScrollView>

@ -0,0 +1,5 @@
import { NativeEventEmitter } from 'react-native';
const eventEmitter = new NativeEventEmitter();
export default eventEmitter;

@ -1,15 +1,16 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet, View, Text, ScrollView, useWindowDimensions} from 'react-native'; import {StyleSheet, View, Text, ScrollView, useWindowDimensions} from 'react-native';
import {LinearGradient} from 'expo-linear-gradient'; import {LinearGradient} from 'expo-linear-gradient';
import {SafeAreaProvider} from 'react-native-safe-area-context'; import {SafeAreaProvider} from 'react-native-safe-area-context';
import ValidateButton from '../components/ValidateButton'; import ValidateButton from '../components/ValidateButton';
import TopBar from '../components/TopBar';
import ListSelect from '../components/ListSelect'; import ListSelect from '../components/ListSelect';
import ListWithoutSelect from '../components/ListWithoutSelect'; import ListWithoutSelect from '../components/ListWithoutSelect';
import ProfileSelection from '../components/ProfileSelection'; import ProfileSelection from '../components/ProfileSelection';
import ColorContext from '../theme/ColorContext';
export default function FiltersSelection(props) { export default function FiltersSelection(props) {
const {colors} = useContext(ColorContext);
const profiles = [ const profiles = [
{name: "Johnny Silverhand", avatar: "plus_small.png", isActive: "flex"}, {name: "Johnny Silverhand", avatar: "plus_small.png", isActive: "flex"},
{name: "Panam Palmer", avatar: "plus_small.png", isActive: "none"}, {name: "Panam Palmer", avatar: "plus_small.png", isActive: "none"},
@ -30,22 +31,83 @@ export default function FiltersSelection(props) {
const dieProfiles = [{value: "Porkless"}, {value: "Pescatarian"}] const dieProfiles = [{value: "Porkless"}, {value: "Pescatarian"}]
function isInProfileDiets(element, index, array) { function isInProfileDiets(element, index, array) {
var retType = true let retType = true
dieProfiles.forEach(function (diets) { dieProfiles.forEach(function (diets) {
if(diets.value==element.value){ if(diets.value==element.value){
retType = false retType = false
} }
}) })
return retType return retType
} }
const dieAdd = die.filter(isInProfileDiets); const dieAdd = die.filter(isInProfileDiets);
const allAdd = [] const allAdd = []
const styles = StyleSheet.create({
container: {
height: "100%",
width: "100%",
flex: 1,
backgroundColor: '#3F3C42',
alignItems: 'center',
justifyContent: 'center',
},
linearGradient: {
height: "100%",
width: "100%",
flex: 1,
padding: "2%",
paddingTop: 0,
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: colors.cardBackground,
padding: "3%",
marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: colors.cardElementBorder,
flex: 1,
},
nbSelected: {
fontSize: 11,
color: colors.cardDetail,
textAlign: "right",
},
profilesSelection: {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: colors.cardBackground,
marginHorizontal: "3%",
paddingBottom: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
});
const goBack = () => props.navigation.goBack();
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<TopBar title="Filters Selection" isVisible="true"/>
<ScrollView> <ScrollView>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<View style={styles.profilesSelection}> <View style={styles.profilesSelection}>
<View style={styles.filterBar}> <View style={styles.filterBar}>
@ -55,7 +117,7 @@ export default function FiltersSelection(props) {
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ProfileSelection listProfile={profiles} disableSelection={false}/> <ProfileSelection listProfile={profiles} disableSelection={false}/>
<View style={{marginTop: "4%"}}/> <View style={{marginTop: "4%"}}/>
<ValidateButton title="Change Selected Profiles" image="update.png" colour="#59BDCD" backColour="#E3DEC9" todo={ () => console.log("change selected profile")}></ValidateButton> <ValidateButton title="Validate Selected Profiles" image="validate.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={ () => console.log("change selected profile")}></ValidateButton>
</View> </View>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<View style={styles.background}> <View style={styles.background}>
@ -76,69 +138,13 @@ export default function FiltersSelection(props) {
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ListWithoutSelect title="Allergies" content={allAdd}></ListWithoutSelect> <ListWithoutSelect title="Allergies" content={allAdd}></ListWithoutSelect>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ValidateButton title="Add Allergy" image="plus.png" colour="#59BDCD" backColour="#E3DEC9" todo={() => console.log("add allergy")}></ValidateButton> <ValidateButton title="Add Allergy" image="plus.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => props.navigation.navigate("IngredientSelection")}></ValidateButton>
</View> </View>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<ValidateButton title="Save Filters" image="save.png" colour="#ACA279" backColour="#F2F0E4" todo={() => console.log("save filters")}></ValidateButton> <ValidateButton title="Save Filters" image="save.png" colour={colors.buttonMain} backColour={colors.cardBackground} todo={goBack}></ValidateButton>
<View style={{marginTop: "20%"}}/> <View style={{marginTop: "20%"}}/>
</LinearGradient> </LinearGradient>
</ScrollView> </ScrollView>
</SafeAreaProvider> </SafeAreaProvider>
); );
} }
const styles = StyleSheet.create({
container: {
height: "100%",
width: "100%",
flex: 1,
backgroundColor: '#3F3C42',
alignItems: 'center',
justifyContent: 'center',
},
linearGradient: {
height: "100%",
width: "100%",
flex: 1,
padding: "2%",
paddingTop: 0,
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: '#F2F0E4',
padding: "3%",
marginHorizontal: "3%",
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: '#ACA279',
flex: 1,
},
nbSelected: {
fontSize: 11,
color: "#3F3C42",
textAlign: "right",
},
profilesSelection: {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: '#F2F0E4',
marginHorizontal: "3%",
paddingBottom: "3%",
},
});

@ -70,7 +70,7 @@ export default function HomePage({ navigation, props }) {
}, },
filters: { filters: {
fontSize: 20, fontSize: 20,
color: colors.cardTitle, color: colors.cardElementBorder,
flex: 1, flex: 1,
}, },
nbSelected: { nbSelected: {
@ -86,6 +86,8 @@ export default function HomePage({ navigation, props }) {
backgroundColor: colors.cardBackground, backgroundColor: colors.cardBackground,
marginHorizontal: "3%", marginHorizontal: "3%",
paddingBottom: "3%", paddingBottom: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
}, },
welcome: { welcome: {
@ -119,6 +121,16 @@ export default function HomePage({ navigation, props }) {
} }
}); });
const nbActiveProfiles = () => {
let cpt = 0
profiles.forEach((val) => {
if(val.isActive == "flex"){
cpt += 1
}
})
return cpt
}
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<ScrollView> <ScrollView>
@ -128,7 +140,7 @@ export default function HomePage({ navigation, props }) {
<View style={{flexDirection: "column", alignItems: "flex-start", justifyContent: "center", width: "100%"}}> <View style={{flexDirection: "column", alignItems: "flex-start", justifyContent: "center", width: "100%"}}>
<View style={{flexDirection: "row"}}> <View style={{flexDirection: "row"}}>
<Text style={styles.text}>Welcome </Text> <Text style={styles.text}>Welcome </Text>
<Text style={styles.name}>Rayhân</Text> <Text style={styles.name}>Louison</Text>
<Text style={styles.text}>,</Text> <Text style={styles.text}>,</Text>
</View> </View>
<Text style={styles.text}>Glad to see you again!</Text> <Text style={styles.text}>Glad to see you again!</Text>
@ -138,22 +150,16 @@ export default function HomePage({ navigation, props }) {
<View style={styles.profilesSelection}> <View style={styles.profilesSelection}>
<View style={styles.filterBar}> <View style={styles.filterBar}>
<Text style={styles.filters}>Profiles</Text> <Text style={styles.filters}>Profiles</Text>
<Text style={styles.nbSelected}>2 selected</Text> <Text style={styles.nbSelected}>{nbActiveProfiles()} selected</Text>
</View> </View>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ProfileSelection listProfile={profiles} disableSelection={true}/> <ProfileSelection listProfile={profiles} disableSelection={true}/>
<View style={{marginTop: "4%"}}/> <View style={{marginTop: "4%"}}/>
<ValidateButton title="Change Active Filters" image="update.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate('FiltersSelection')}/>
<View style={{marginTop: "3%"}}/>
<ValidateButton title="Modify Profiles" image="parameter.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate('Profiles')}/> <ValidateButton title="Modify Profiles" image="parameter.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate('Profiles')}/>
</View> </View>
<View style={styles.separator}/> <View style={styles.separator}/>
<View style={styles.profilesSelection}>
<View style={styles.filterBar}>
<Text style={styles.filters}>Ingredient Stocks</Text>
</View>
<View style={{marginTop: "4%"}}/>
<ValidateButton title="Manage Stocks" image="warehouse.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => console.log('ManageStocks')}/>
</View>
<View style={styles.separator}/>
<View style={styles.profilesSelection}> <View style={styles.profilesSelection}>
<View style={styles.filterBar}> <View style={styles.filterBar}>
<Text style={styles.filters}>Cooking</Text> <Text style={styles.filters}>Cooking</Text>
@ -161,20 +167,20 @@ export default function HomePage({ navigation, props }) {
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<View style={styles.ingredientSelection}> <View style={styles.ingredientSelection}>
<Text style={{fontSize: 15, color: colors.carrouselText}}>Selected Ingredient</Text> <Text style={{fontSize: 15, color: colors.carrouselText}}>Selected Ingredient</Text>
<View style={{flexDirection: "row", padding: "4%", justifyContent: "center", alignItems: "center"}}> <View style={{flexDirection: "row", padding: "4%", justifyContent: "center", alignItems: "center", marginLeft: "8%"}}>
<Pressable onPress={decreaseCounter}> <Pressable onPress={decreaseCounter}>
<Image source={bracketLeft} style={{width: 40, height: 40, resizeMode: "contain"}} tintColor={colors.carrouselText}/> <Image source={bracketLeft} style={{width: 40, height: 40, resizeMode: "contain"}} tintColor={colors.carrouselText}/>
</Pressable> </Pressable>
<FoodElementText title={ingredientList[cpt].title}/> <FoodElementText title={ingredientList[cpt].title} mainColour={colors.carrouselBackground} secondaryColour={colors.cardDetail}/>
<Pressable onPress={increaseCounter}> <Pressable onPress={increaseCounter}>
<Image source={bracketRight} style={{width: 40, height: 40, resizeMode: "contain"}} tintColor={colors.carrouselText} /> <Image source={bracketRight} style={{width: 40, height: 40, resizeMode: "contain"}} tintColor={colors.carrouselText} />
</Pressable> </Pressable>
</View> </View>
</View> </View>
<View style={{marginTop: "4%"}}/> <View style={{marginTop: "4%"}}/>
<ValidateButton title="Change Selected Ingredients" image="cook.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={ () => console.log('Chnge Selected Ingredient')}/> <ValidateButton title="Change Selected Ingredients" image="cook.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate('IngredientSelection')}/>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ValidateButton title="Search Recipes" image="search.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={ () => console.log('Go and search for recipe')}/> <ValidateButton title="Search Recipes" image="search.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate('RecipeSuggestion')}/>
</View> </View>
<View style={{marginBottom: "20%"}}/> <View style={{marginBottom: "20%"}}/>
</LinearGradient> </LinearGradient>

@ -1,14 +1,14 @@
import React, { useEffect, useState, useContext } from 'react'; import React, { useEffect, useState, useContext } from 'react';
import { View, StyleSheet, Text, Image, Pressable, ActivityIndicator, FlatList, ScrollView, useWindowDimensions } from 'react-native'; import { View, StyleSheet, Text, Image, Pressable, ActivityIndicator, FlatList, useWindowDimensions } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Searchbar } from 'react-native-paper'; import { Searchbar } from 'react-native-paper';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import FoodElementText from '../components/FoodElementText'; import FoodElementText from '../components/FoodElementText';
import CustomButton from '../components/CustomButton';
import Ingredient from '../Models/Ingredient'; import Ingredient from '../Models/Ingredient';
import IngredientService from '../Services/Ingredients/IngredientsServices'; import IngredientService from '../Services/Ingredients/IngredientsServices';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
import ValidateButton from '../components/ValidateButton';
import plus from '../assets/images/plus.png'; import plus from '../assets/images/plus.png';
import moins from '../assets/images/minus.png'; import moins from '../assets/images/minus.png';
@ -18,31 +18,30 @@ export default function IngredientSelection(props) {
const alphabetArray: Array<string> = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]; const alphabetArray: Array<string> = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState();
const [response, setResponse] = useState<Ingredient[] | undefined>(undefined); const [response, setResponse] = useState<Ingredient[] | undefined>(undefined);
const [selectedIngredients, setSelectedIngredients] = useState([]); const [selectedIngredients, setSelectedIngredients] = useState([]);
const ingredientService = new IngredientService(); const ingredientService = new IngredientService();
const [availableSize, setAvailableSize] = useState(0);
const [listVisibility, setListVisibility] = useState("none");
const [availableVisibility, setAvailableVisibility] = useState("none");
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const filterIngredients = async (query) => { const filterIngredients = async (query) => {
try { try {
setIsLoading(true); setIsLoading(true);
if (query === '') { if (query === '') {
// Si le query (prompt) est vide, charger tous les ingrédients
loadIngredients(); loadIngredients();
} else { } else {
const filtered = await ingredientService.getfilteredIngredient(query); const filtered = await ingredientService.getfilteredIngredient(query);
setResponse(filtered); setResponse(filtered);
} }
} catch (error) { } catch (error) {
setError(error); console.log(error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}; };
// Appelée à chaque changement de la recherche
const handleSearch = (query) => { const handleSearch = (query) => {
setSearchQuery(query); setSearchQuery(query);
filterIngredients(query); filterIngredients(query);
@ -53,7 +52,7 @@ const loadIngredients = async () => {
const ingredients = await ingredientService.getAllIngredient(); const ingredients = await ingredientService.getAllIngredient();
setResponse(ingredients); setResponse(ingredients);
} catch (error) { } catch (error) {
setError(error); console.log(error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
@ -66,12 +65,12 @@ const loadIngredients = async () => {
const AvailableItem = ({ value }: { value: Ingredient }) => ( const AvailableItem = ({ value }: { value: Ingredient }) => (
<> <>
<View style={styles.horizontalAlignment}> <View style={styles.horizontalAlignment}>
<FoodElementText title={value.name} /> <FoodElementText title={value.name}/>
<Pressable onPress={() => SelectIngredient(value)}> <Pressable onPress={() => SelectIngredient(value)}>
<Image source={plus} style={{ width: 20, height: 20 }} /> <Image source={plus} style={{ width: 20, height: 20, tintColor: colors.cardDetail }} />
</Pressable> </Pressable>
</View> </View>
<View style={{ height: 30 }}></View> <View style={{ height: 20 }}></View>
</> </>
); );
@ -80,83 +79,173 @@ const loadIngredients = async () => {
<View style={styles.horizontalAlignment}> <View style={styles.horizontalAlignment}>
<FoodElementText title={value.name} /> <FoodElementText title={value.name} />
<Pressable onPress={() => RemoveIngredient(value.id)}> <Pressable onPress={() => RemoveIngredient(value.id)}>
<Image source={moins} style={{ width: 20, height: 20 }} /> <Image source={moins} style={{ width: 20, height: 20, tintColor: colors.cardDetail }} />
</Pressable> </Pressable>
</View> </View>
<View style={{ height: 30 }}></View> <View style={{ height: 20 }}></View>
</> </>
); );
const SelectIngredient = (newIngredient: Ingredient) => { const SelectIngredient = (newIngredient: Ingredient) => {
const exists = selectedIngredients.find((ingredient) => ingredient.id === newIngredient.id); const exists = selectedIngredients.find((ingredient) => ingredient.id === newIngredient.id);
if (!exists) { if (!exists) {
setSelectedIngredients([...selectedIngredients, newIngredient]); setSelectedIngredients([...selectedIngredients, newIngredient]);
ChangeAvailableSize(false)
} }
}; };
const RemoveIngredient = (idIngredient: number) => { const RemoveIngredient = (idIngredient: number) => {
const updatedIngredients = selectedIngredients.filter((ingredient) => ingredient.id !== idIngredient); const updatedIngredients = selectedIngredients.filter((ingredient) => ingredient.id !== idIngredient);
setSelectedIngredients(updatedIngredients); setSelectedIngredients(updatedIngredients);
ChangeAvailableSize(true)
}; };
const ChangeAvailableSize = (remove: boolean) => {
if(remove){
if (selectedIngredients.length == 1){
setAvailableSize(0)
}
else if (selectedIngredients.length == 2){
setAvailableSize(90)
}
else if (selectedIngredients.length == 3){
setAvailableSize(180)
}
else if (selectedIngredients.length == 4){
setAvailableSize(260)
}
else{
setAvailableSize(280)
}
}
else{
if (selectedIngredients.length == 0){
setAvailableSize(90)
}
else if (selectedIngredients.length == 1){
setAvailableSize(180)
}
else if (selectedIngredients.length == 2){
setAvailableSize(260)
}
else{
setAvailableSize(280)
}
}
}
const handleLetterPress = async (letter: string) => { const handleLetterPress = async (letter: string) => {
try { try {
const ingredientsByLetter = await ingredientService.getIngredientByLetter(letter); const ingredientsByLetter = await ingredientService.getIngredientByLetter(letter);
setResponse(ingredientsByLetter); setResponse(ingredientsByLetter);
} catch (error) { } catch (error) {
setError(error); console.log(error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
}; };
const changeListVisibility = () => {
if(listVisibility == "none"){
setListVisibility("flex")
}
else{
setListVisibility("none")
}
};
const changeAvailableVisibility = () => {
if(availableVisibility == "none"){
setAvailableVisibility("flex")
}
else{
setAvailableVisibility("none")
}
};
const styles = StyleSheet.create({
linearGradient: {
width: "100%",
flex: 1,
padding: "3%",
paddingTop: 0,
alignItems: "center",
justifyContent: "flex-start",
},
element: {
width: "100%",
backgroundColor: colors.cardBackground,
borderRadius: 30,
borderWidth: 1,
borderColor: colors.blocBorder,
},
horizontalAlignment: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
marginTop: "3%",
}
});
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<ScrollView> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<View style={styles.element}> <View style={styles.element}>
<View style={[styles.horizontalAlignment, { margin: 10 }]}> <View style={{justifyContent: "center"}}>
{alphabetArray.map((source, index) => ( <Pressable onPress={changeListVisibility} style={{alignItems: "center"}}>
<Pressable key={index} onPress={() => handleLetterPress(source)}> <Image source={require("../assets/images/arrow.png")} style={{tintColor: colors.cardDetail}}/>
<Text style={{ color: "blue" }}>{source}</Text> </Pressable>
</Pressable>
))}
</View> </View>
<View style={{display: listVisibility}}>
<View style={[styles.horizontalAlignment, { margin: "2%" }]}>
{alphabetArray.map((source, index) => (
<Pressable key={index} onPress={() => handleLetterPress(source)}>
<Text style={{ color: colors.letterFilter }}>{source}</Text>
</Pressable>
))}
</View>
<View> <View>
<Searchbar <Searchbar
placeholder="Search" placeholder="Search"
onChangeText={handleSearch} onChangeText={handleSearch}
value={searchQuery} value={searchQuery}
style={{margin: "3%", iconColor={colors.cardDetail}
backgroundColor: '#F2F0E4', inputStyle={{color: colors.cardDetail}}
borderWidth : 1, rippleColor={colors.letterFilter}
borderColor: "#ACA279", style={{margin: "3%",
borderRadius: 15, backgroundColor: colors.cardBackground,
}}/> borderWidth : 1,
borderColor: colors.cardElementBorder,
borderRadius: 15,
}}/>
</View> </View>
<View style={{flex: 1, maxHeight: 300}}> <View style={{height: 280}}>
<FlatList <FlatList
data={response ? response : []} data={response ? response : []}
renderItem={({ item }) => ( renderItem={({ item }) => (
<AvailableItem value={item} /> <AvailableItem value={item} />
)} )}
keyExtractor={(item, index) => index.toString()} keyExtractor={(item, index) => index.toString()}
ListEmptyComponent={() => ( ListEmptyComponent={() => (
isLoading ? <ActivityIndicator size="large" /> : <Text>Erreur lors du traitement des données</Text> isLoading ? <ActivityIndicator size="large" /> : <Text>Erreur lors du traitement des données</Text>
)} )}
style={{ flex: 1 }} style={{ flex: 1 }}
/> />
<View style={{ marginTop: '6%' }}></View> <View style={{ marginTop: '6%' }}></View>
</View> </View>
</View>
</View> </View>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<View style={styles.element}> <View style={styles.element}>
<View style={[styles.horizontalAlignment, {justifyContent: "flex-start", marginLeft: "5%"}]}> <Pressable onPress={changeAvailableVisibility}>
<Text style={{fontSize: 20, color: '#ACA279'}}>Available</Text> <View style={[styles.horizontalAlignment, {justifyContent: "flex-start", marginHorizontal: "5%", marginBottom: "4%"}]}>
</View> <Text style={{fontSize: 20, color: colors.cardElementBorder, flex: 1}}>Available</Text>
<View style={{flex: 1, maxHeight: 300}}> <Image source={require("../assets/images/arrow.png")} style={{tintColor: colors.cardDetail}}/>
</View>
</Pressable>
<View style={{height: availableSize, display: availableVisibility}}>
<FlatList <FlatList
data={selectedIngredients} data={selectedIngredients}
renderItem={({ item }) => ( renderItem={({ item }) => (
@ -164,39 +253,14 @@ const loadIngredients = async () => {
)} )}
keyExtractor={(item, index) => index.toString()} keyExtractor={(item, index) => index.toString()}
style={{ flex: 1 }} style={{ flex: 1 }}
/> />
<View style={{ height: 20 }}></View> <View style={{ height: 20 }}></View>
</View> </View>
</View> </View>
<View style={{marginTop: "8%"}}></View> <View style={{marginTop: "8%"}}></View>
<CustomButton title="Find a recipe"/> <ValidateButton title="Find a recipe" image="validate.png" colour={colors.buttonMain} backColour={colors.cardBackground} todo={() => props.navigation.navigate("RecipeSuggestion")}/>
<View style={{marginBottom: "20%"}}></View> <View style={{marginBottom: "20%"}}></View>
</LinearGradient> </LinearGradient>
</ScrollView>
</SafeAreaProvider> </SafeAreaProvider>
); );
} }
const styles = StyleSheet.create({
linearGradient: {
width: "100%",
flex: 1,
padding: "3%",
paddingTop: 0,
alignItems: "center",
justifyContent: "flex-start",
},
element: {
width: "100%",
backgroundColor:'#F2F0E4',
borderRadius: 30,
},
horizontalAlignment: {
width: "100%",
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
marginTop: "3%",
}
});

@ -1,4 +1,4 @@
import React from 'react'; import React, {useContext} from 'react';
import {StyleSheet, View, ScrollView, useWindowDimensions} from 'react-native'; import {StyleSheet, View, ScrollView, useWindowDimensions} from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
@ -6,18 +6,21 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
import ProfileModification from '../components/ProfileModification'; import ProfileModification from '../components/ProfileModification';
import ValidateButton from '../components/ValidateButton'; import ValidateButton from '../components/ValidateButton';
import ColorContext from '../theme/ColorContext'
export default function ModifyProfile(props) { export default function ModifyProfile(props) {
const {colors} = useContext(ColorContext);
const all = [{value: "Mussels"}, {value: "Skimmed Milk"}, {value: "Nuts"}] const all = [{value: "Mussels"}, {value: "Skimmed Milk"}, {value: "Nuts"}]
const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}] const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<ScrollView style={{minHeight: useWindowDimensions().height}}> <ScrollView style={{minHeight: useWindowDimensions().height}}>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<ProfileModification name="Johnny Silverhand" avatar="plus_small.png" diets={die} allergies={all}></ProfileModification> <ProfileModification name="Johnny Silverhand" avatar="plus_small.png" diets={die} allergies={all}></ProfileModification>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ValidateButton title="Update Profile" image="update.png" colour="#ACA279" backColour="#F2F0E4" todo={() => (console.log("Profile Modified"))}></ValidateButton> <ValidateButton title="Update Profile" image="update.png" colour={colors.buttonMain} backColour={colors.cardBackground} todo={() => (console.log("Profile Modified"))}></ValidateButton>
<View style={{marginBottom: "20%"}}/> <View style={{marginTop: "20%"}}/>
</LinearGradient> </LinearGradient>
</ScrollView> </ScrollView>
</SafeAreaProvider> </SafeAreaProvider>
@ -25,14 +28,6 @@ export default function ModifyProfile(props) {
} }
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: {
height: "100%",
width: "100%",
flex: 1,
backgroundColor: '#3F3C42',
alignItems: 'center',
justifyContent: 'center',
},
linearGradient: { linearGradient: {
height: "100%", height: "100%",
width: "100%", width: "100%",

@ -1,4 +1,4 @@
import React, { useContext, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { StyleSheet, View, Modal, Pressable, Text, Image, ScrollView, useWindowDimensions } from 'react-native'; import { StyleSheet, View, Modal, Pressable, Text, Image, ScrollView, useWindowDimensions } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
@ -7,51 +7,86 @@ import { SafeAreaProvider } from 'react-native-safe-area-context';
import ProfileDetails from '../components/ProfileDetails'; import ProfileDetails from '../components/ProfileDetails';
import ProfileDelete from '../components/ProfileDelete'; import ProfileDelete from '../components/ProfileDelete';
import ColorContext from '../theme/ColorContext'; import ColorContext from '../theme/ColorContext';
import AsyncStorage from '@react-native-async-storage/async-storage';
import EventEmitter from './EventEmitter';
import Profil from '../Models/Profil';
import { PaperProvider, Portal } from 'react-native-paper';
export default function Profiles({navigation, props}) { export default function Profiles({navigation, props}) {
const colors = useContext(ColorContext).colors const colors = useContext(ColorContext).colors
const allJohnny = [{value: "Coconut"}, {value: "Skimmed Milk"}, {value: "Nuts"}] const all = []
const dieJohnny = [{value: "Gluten free"}, {value: "Porkless"}, {value: "Pescatarian"}] const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}]
const allJackie = [{value: "Tomato"}, {value: "Relic"}]
const dieJackie = [{value: "Porkless"}, {value: "Vegetarian"}]
const allGoro = []
const dieGoro = [{value: "Pescatarian"}]
const allViktor = [{value: "Pasta"}, {value: "Fish"}]
const dieViktor = [{value: "Dairy free"}, {value: "Vegan"}]
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [opacity, setOpacity] = useState(1); const [opacity, setOpacity] = useState(1);
const raisePopUp = () => { const [profiles, setProfiles] = useState([]);
const [selectedProfileIndex, setSelectedProfileIndex] = useState(null);
const raisePopUp = (index) => {
setSelectedProfileIndex(index)
setVisible(true) setVisible(true)
setOpacity(0.3)
} }
const erasePopUp = () => { const erasePopUp = () => {
setVisible(false) setVisible(false)
setOpacity(1)
} }
const profiles = [ const handleDeleteProfiles = async () => {
{ try {
name: "Johnny Silverhand", await AsyncStorage.removeItem('profiles');
avatar: "plus_small.png", console.log('Données supprimées avec succès !');
diets: dieJohnny, } catch (error) {
allergies: allJohnny, console.error('Erreur lors de la suppression des données :', error);
}, }
{ };
name: "Jackie Welles",
avatar: "plus_small.png", const handleDeleteProfile = async (index) => {
diets: dieJackie, try {
allergies: allJackie, const updatedProfiles = profiles.filter((profile, i) => i !== index);
}, await AsyncStorage.setItem('profiles', JSON.stringify(updatedProfiles));
// ... Ajoutez d'autres profils ici de la même manière fetchProfiles();
]; setSelectedProfileIndex(index);
erasePopUp();
} catch (error) {
console.error('Erreur lors de la suppression du profil :', error);
}
};
const confirmDelete = () => {
erasePopUp();
};
const handleGetProfiles = async () => {
try {
const existingProfiles = await AsyncStorage.getItem('profiles');
return JSON.parse(existingProfiles) || [];
} catch (error) {
console.log("ça maaaaaaaaarche poaaaaaaaaaaaas");
return [];
}
}
const fetchProfiles = async () => {
const existingProfiles = await handleGetProfiles();
setProfiles(existingProfiles);
};
const subscription = EventEmitter.addListener('profileAdded', async () => {
fetchProfiles();
});
useEffect(() => {
fetchProfiles();
console.log(profiles)
}, []);
const containerStyle = {
height: "75%",
width: "100%",
};
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
height: "100%", height: "100%",
width: "100%", width: "100%",
@ -74,7 +109,7 @@ export default function Profiles({navigation, props}) {
modal: { modal: {
position: 'absolute', position: 'absolute',
top: '8%', top: '0%',
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
width: "100%", width: "100%",
@ -102,11 +137,13 @@ export default function Profiles({navigation, props}) {
borderRadius: 15, borderRadius: 15,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
backgroundColor: "#F2F0E4", backgroundColor: colors.cardBackground,
borderWidth: 1,
borderColor: colors.blocBorder,
}, },
validationQuestion: { validationQuestion: {
fontSize: 20, fontSize: 20,
color: '#ACA279', color: colors.cardElementBorder,
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
flex: 0.3, flex: 0.3,
@ -129,7 +166,7 @@ export default function Profiles({navigation, props}) {
borderRadius: 20, borderRadius: 20,
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
backgroundColor: "#59BDCD", backgroundColor: colors.yesButton,
}, },
yesText: { yesText: {
fontSize: 20, fontSize: 20,
@ -163,55 +200,63 @@ export default function Profiles({navigation, props}) {
const profileComponents = profiles.map((profile, index) => ( const profileComponents = profiles.map((profile, index) => (
<View key={index}> <View key={index}>
<ProfileDetails <ProfileDetails
name={profile.name} name={profile.name}
avatar={profile.avatar} avatar={profile.avatar}
diets={profile.diets} diets={profile.diets}
allergies={profile.allergies} allergies={profile.allergies}
onDeleteProfile={raisePopUp} onDeleteProfile={() => raisePopUp(index)}
/> />
<Portal>
<Modal visible={visible} onDismiss={erasePopUp} contentContainerStyle={containerStyle} style={{marginTop: 0, justifyContent: "flex-start"}}>
<View style={styles.modal}>
<View style={styles.viewModal}>
<View style={styles.profileValidation}>
{/* <ProfileDelete
name={profiles[selectedProfileIndex].name}
avatar={profiles[selectedProfileIndex].avatar}
diets={profiles[selectedProfileIndex].diets}
allergies={profiles[selectedProfileIndex].allergies}
/> */}
</View>
<View style={styles.decisionBarVertical}>
<Text style={styles.validationQuestion}>Do you really want to delete this profile?</Text>
<View style={styles.decisionBar}>
<Pressable onPress={() => handleDeleteProfile(selectedProfileIndex)} style={{flex:0.5}}>
<View style={styles.yesButton}>
<Image source={require("../assets/images/validate.png")} style={{tintColor: "#2DE04A", height: "100%", flex: 0.2, margin: "5%", resizeMode: "contain"}}/>
<Text style={styles.yesText}>Yes</Text>
</View>
</Pressable>
<Pressable onPress={erasePopUp} style={{flex:0.5}}>
<View style={styles.noButton}>
<Image source={require("../assets/images/cross.png")} style={{tintColor: "#E02D2D", height: "100%", flex: 0.2, margin: "5%", resizeMode: "contain"}}/>
<Text style={styles.noText}>No</Text>
</View>
</Pressable>
</View>
</View>
</View>
</View>
</Modal>
</Portal>
{index < profiles.length - 1 && <View style={styles.separator} />} {index < profiles.length - 1 && <View style={styles.separator} />}
</View> </View>
)); ));
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<ScrollView> <PaperProvider>
<View style={{opacity: opacity, height: "100%", width: "100%", flex: 1}}> <ScrollView>
<LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={styles.separator}/> <View style={styles.separator}/>
{profileComponents} {profileComponents}
<View style={styles.modal}>
<Modal visible={visible} onRequestClose={erasePopUp} animationType="fade" transparent={true}>
<View style={styles.modal}>
<View style={styles.viewModal}>
<View style={styles.profileValidation}>
<ProfileDelete name="Johnny Silverhand" avatar="plus_small.png" diets={dieJohnny} allergies={allJohnny}></ProfileDelete>
</View>
<View style={styles.decisionBarVertical}>
<Text style={styles.validationQuestion}>Do you really want to delete this profile?</Text>
<View style={styles.decisionBar}>
<Pressable onPress={erasePopUp} style={{flex:0.5}}>
<View style={styles.yesButton}>
<Image source={require("../assets/images/validate.png")} style={{tintColor: "#2DE04A", height: "100%", flex: 0.2, margin: "5%", resizeMode: "contain"}}/>
<Text style={styles.yesText}>Yes</Text>
</View>
</Pressable>
<Pressable onPress={erasePopUp} style={{flex:0.5}}>
<View style={styles.noButton}>
<Image source={require("../assets/images/cross.png")} style={{tintColor: "#E02D2D", height: "100%", flex: 0.2, margin: "5%", resizeMode: "contain"}}/>
<Text style={styles.noText}>No</Text>
</View>
</Pressable>
</View>
</View>
</View>
</View>
</Modal>
</View>
<View style={{marginBottom: "20%"}}/> <View style={{marginBottom: "20%"}}/>
</LinearGradient> </LinearGradient>
</View> </ScrollView>
</ScrollView>
</PaperProvider>
</SafeAreaProvider> </SafeAreaProvider>
); );
} }

@ -1,19 +1,19 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState, useContext } from 'react';
import { View, StyleSheet, Text, ScrollView, useWindowDimensions} from 'react-native'; import { View, StyleSheet, Text, ScrollView, useWindowDimensions} from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import RecipeElementReduce from '../components/RecipeElementReduce'; import RecipeElementReduce from '../components/RecipeElementReduce';
import AllergiesTab from '../components/ListWithoutSelect';
import RecipesService from '../Services/Recipes/RecipesServices'; import RecipesService from '../Services/Recipes/RecipesServices';
import Recipes from '../Models/Recipes'; import Recipes from '../Models/Recipes';
import { LinearGradient } from 'expo-linear-gradient'; import { LinearGradient } from 'expo-linear-gradient';
import ListWithoutSelect from '../components/ListWithoutSelect'; import ListWithoutSelect from '../components/ListWithoutSelect';
import ColorContext from '../theme/ColorContext';
export default function RecipeDetails(props) { export default function RecipeDetails(props) {
const {colors} = useContext(ColorContext);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState();
const [response, setResponse] = useState<Recipes | undefined>(undefined); const [response, setResponse] = useState<Recipes | undefined>(undefined);
const recipesService = new RecipesService(); const recipesService = new RecipesService();
@ -22,7 +22,7 @@ export default function RecipeDetails(props) {
const recipe = await recipesService.getRecipeById(props.id); const recipe = await recipesService.getRecipeById(props.id);
setResponse(recipe); setResponse(recipe);
} catch (error) { } catch (error) {
setError(error); console.log(error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
@ -40,18 +40,60 @@ export default function RecipeDetails(props) {
const minutesString = minutes > 0 ? ` ${minutes} min` : ''; const minutesString = minutes > 0 ? ` ${minutes} min` : '';
return `${hoursString}${minutesString}`.trim(); return `${hoursString}${minutesString}`.trim();
} }
return ( const styles = StyleSheet.create({
linearGradient: {
width: "100%",
flex: 1,
alignItems: "center",
justifyContent: "flex-start"
},
separator: {
marginTop: "6%",
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: '#F2F0E4',
padding: "3%",
marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: '#ACA279',
flex: 1,
},
nbSelected: {
fontSize: 11,
color: "#3F3C42",
textAlign: "right",
},
});
return (
<SafeAreaProvider> <SafeAreaProvider>
<ScrollView> <ScrollView>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}> <View style={{marginTop: "6%"}}>
<RecipeElementReduce <RecipeElementReduce
title={response.name} title={response.name}
number={response.id} number={response.id}
duration={convertToHoursMinutes(response.time_to_cook)} image={''}/> duration={convertToHoursMinutes(response.time_to_cook)} image={''}/>
</View> </View>
<View style={styles.separator}/> <View style={styles.separator}/>
<View style={styles.background}> <View style={styles.background}>
@ -74,46 +116,4 @@ export default function RecipeDetails(props) {
</ScrollView> </ScrollView>
</SafeAreaProvider> </SafeAreaProvider>
); );
} }
const styles = StyleSheet.create({
linearGradient: {
width: "100%",
flex: 1,
alignItems: "center",
justifyContent: "flex-start"
},
separator: {
marginTop: "6%",
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: '#F2F0E4',
padding: "3%",
marginHorizontal: "3%",
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: '#ACA279',
flex: 1,
},
nbSelected: {
fontSize: 11,
color: "#3F3C42",
textAlign: "right",
},
});

@ -1,19 +1,14 @@
import React, { useState } from 'react'; import React, { useState, useContext } from 'react';
import {View, StyleSheet, Text, Image, Pressable, useWindowDimensions, ScrollView} from 'react-native'; import {View, StyleSheet, Text, Image, Pressable, useWindowDimensions, ScrollView} from 'react-native';
import {SafeAreaProvider } from 'react-native-safe-area-context'; import {SafeAreaProvider } from 'react-native-safe-area-context';
import {Modal, Portal, PaperProvider} from 'react-native-paper'; import {Modal, Portal, PaperProvider} from 'react-native-paper';
import {LinearGradient} from 'expo-linear-gradient'; import {LinearGradient} from 'expo-linear-gradient';
import TopBar from '../components/TopBar';
import RecipeElement from '../components/RecipeElement'; import RecipeElement from '../components/RecipeElement';
import SelectedIngredient from '../components/SelectedIngredient'; import SelectedIngredient from '../components/SelectedIngredient';
import FoodElementTextSimple from '../components/FoodElementTextSimple'; import FoodElementTextSimple from '../components/FoodElementTextSimple';
import FoodElementText from '../components/FoodElementText';
import CustomButton from '../components/CustomButton'; import CustomButton from '../components/CustomButton';
import DietsTab from '../components/ListSelect'; import ColorContext from '../theme/ColorContext';
import brochette from '../assets/images/brochette.png';
import ParameterTopBar from '../components/ParameterTopBar'; import ParameterTopBar from '../components/ParameterTopBar';
import ListSelect from '../components/ListSelect';
import ListWithoutSelect from '../components/ListWithoutSelect'; import ListWithoutSelect from '../components/ListWithoutSelect';
import ValidateButton from '../components/ValidateButton'; import ValidateButton from '../components/ValidateButton';
import bracketLeft from '../assets/images/angle_bracket_left.png'; import bracketLeft from '../assets/images/angle_bracket_left.png';
@ -23,6 +18,7 @@ import minus from '../assets/images/minus.png';
export default function RecipeSuggestion(props) { export default function RecipeSuggestion(props) {
const {colors} = useContext(ColorContext)
const [visible, setVisible] = React.useState(false); const [visible, setVisible] = React.useState(false);
const [visibleFilters, setVisibleFilters] = React.useState(false); const [visibleFilters, setVisibleFilters] = React.useState(false);
const [visibleIngredients, setVisibleIngredients] = React.useState(true); const [visibleIngredients, setVisibleIngredients] = React.useState(true);
@ -32,7 +28,7 @@ export default function RecipeSuggestion(props) {
const ingredientListV2 = [{title: "Smoked Salmon"}, {title: "Tomato"}, {title: "Carrot"}] const ingredientListV2 = [{title: "Smoked Salmon"}, {title: "Tomato"}, {title: "Carrot"}]
const limitedList = ingredientList.slice(minCpt, maxCpt); const limitedList = ingredientList.slice(minCpt, maxCpt);
const [colorIngredients, setColorIngredients] = useState("#59BDCD"); const [colorIngredients, setColorIngredients] = useState("#59BDCD");
const [colorFilters, setColorFilters] = useState("#3F3C42"); const [colorFilters, setColorFilters] = useState(colors.cardDetail);
const die = [{value: "Gluten free"}, {value: "Porkless"}, {value: "Gluten free"}, {value: "Porkless"}] const die = [{value: "Gluten free"}, {value: "Porkless"}, {value: "Gluten free"}, {value: "Porkless"}]
const all = [] const all = []
@ -52,14 +48,14 @@ export default function RecipeSuggestion(props) {
const handleChildEventGoFilters = () => { const handleChildEventGoFilters = () => {
setVisibleIngredients(false); setVisibleIngredients(false);
setVisibleFilters(true); setVisibleFilters(true);
setColorFilters("#59BDCD") setColorFilters(colors.buttonDetail)
setColorIngredients("#3F3C42") setColorIngredients(colors.cardDetail)
} }
const handleChildEventGoIngredients = () => { const handleChildEventGoIngredients = () => {
setVisibleFilters(false); setVisibleFilters(false);
setVisibleIngredients(true); setVisibleIngredients(true);
setColorFilters("#3F3C42") setColorFilters(colors.cardDetail)
setColorIngredients("#59BDCD") setColorIngredients(colors.buttonDetail)
} }
const decreaseCounter = () => { const decreaseCounter = () => {
@ -69,7 +65,7 @@ export default function RecipeSuggestion(props) {
} }
else{ else{
setMaxCpt(ingredientList.length+ingredientList.length%4) setMaxCpt(ingredientList.length+ingredientList.length%4)
var cpt=ingredientList.length-(ingredientList.length%4) let cpt=ingredientList.length-(ingredientList.length%4)
setMinCpt(cpt) setMinCpt(cpt)
} }
} }
@ -84,20 +80,79 @@ export default function RecipeSuggestion(props) {
} }
} }
const imageElements = limitedList.map((source, index) => ( const styles = StyleSheet.create({
<View style={[styles.horizontalAlignment, {marginVertical: "3%"}]}> linearGradient: {
<FoodElementTextSimple title={source.title}/> width: "100%",
<Image source={plus} style={{width: 20, resizeMode: "contain"}}/> flex: 1,
<Image source={minus} style={{width: 20, resizeMode: "contain"}}/> //padding: "2%",
</View> paddingTop: 0,
alignItems: "center",
justifyContent: "center"
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: colors.cardBackground,
padding: "3%",
marginHorizontal: "3%",
borderWidth: 1,
borderColor: colors.blocBorder,
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: colors.cardElementBorder,
flex: 1,
},
nbSelected: {
fontSize: 11,
color: colors.cardDetail,
textAlign: "right",
},
horizontalAlignment: {
display: 'flex',
height: "10%",
width: "100%",
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
recipes: {
flexDirection: "row",
overflow: "scroll",
alignItems: "flex-start",
justifyContent: "center",
},
});
const ingredientElements = limitedList.map((source, index) => (
<View style={[styles.horizontalAlignment, {marginVertical: "3%"}]}>
<FoodElementTextSimple title={source.title}/>
<Image source={plus} style={{width: 20, resizeMode: "contain", tintColor: colors.cardDetail}}/>
<Image source={minus} style={{width: 20, resizeMode: "contain", tintColor: colors.cardDetail}}/>
</View>
)); ));
const goDetails = () => props.navigation.navigate("RecipeDetails")
return ( return (
<SafeAreaProvider style={{flex: 1}}> <SafeAreaProvider style={{flex: 1}}>
<PaperProvider> <PaperProvider>
<TopBar title="Recipes" isVisible="true"/>
<ScrollView> <ScrollView>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<SelectedIngredient <SelectedIngredient
ingredientList={ingredientList} ingredientList={ingredientList}
@ -108,13 +163,17 @@ export default function RecipeSuggestion(props) {
number="63" number="63"
title="Meat Stick" title="Meat Stick"
textList={ingredientList} textList={ingredientList}
description="Delicious stick with 4 meats. Accessible for beginners. 20 min or less to cook."/> description="Delicious stick with 4 meats. Accessible for beginners. 20 min or less to cook."
duration="17 min"
navigateDetails={goDetails}/>
<View style={{marginHorizontal: 10}}/> <View style={{marginHorizontal: 10}}/>
<RecipeElement <RecipeElement
number="03" number="03"
title="Vichyssoise" title="Vichyssoise"
textList={ingredientListV2} textList={ingredientListV2}
description="Cold soup of vegetables. Difficult recipe. Not advised to beginners. 1h or more."/> description="Cold soup of vegetables. Difficult recipe. Not advised to beginners. 1h or more."
duration="1h and a half"
navigateDetails={goDetails}/>
<View style={{marginHorizontal: 10}}/> <View style={{marginHorizontal: 10}}/>
</ScrollView> </ScrollView>
<View style={{marginBottom: "20%"}}/> <View style={{marginBottom: "20%"}}/>
@ -124,15 +183,15 @@ export default function RecipeSuggestion(props) {
<Modal visible={visible} onDismiss={handleChildEvent} contentContainerStyle={containerStyle} style={{marginTop: 0, justifyContent: "flex-end"}}> <Modal visible={visible} onDismiss={handleChildEvent} contentContainerStyle={containerStyle} style={{marginTop: 0, justifyContent: "flex-end"}}>
<ParameterTopBar onEventFilter={handleChildEventGoFilters} onEventIngredient={handleChildEventGoIngredients} colorFilters={colorFilters} colorIngredients={colorIngredients}/> <ParameterTopBar onEventFilter={handleChildEventGoFilters} onEventIngredient={handleChildEventGoIngredients} colorFilters={colorFilters} colorIngredients={colorIngredients}/>
{visibleIngredients &&( {visibleIngredients &&(
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {paddingHorizontal: "3%"}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {paddingHorizontal: "3%", justifyContent: "flex-start"}]}>
{imageElements} {ingredientElements}
<View style={[styles.horizontalAlignment, {marginTop: "6%"}]}> <View style={[styles.horizontalAlignment, {marginTop: "3%"}]}>
<Pressable onPress={decreaseCounter}> <Pressable onPress={decreaseCounter}>
<Image source={bracketLeft} style={{width: 30, height: "100%", resizeMode: "contain", tintColor: "#3F3C42"}}/> <Image source={bracketLeft} style={{width: 30, height: "100%", resizeMode: "contain", tintColor: colors.cardDetail}}/>
</Pressable> </Pressable>
<CustomButton title="Save"></CustomButton> <CustomButton title="Save"></CustomButton>
<Pressable onPress={increaseCounter}> <Pressable onPress={increaseCounter}>
<Image source={bracketRight} style={{width: 30, height: "100%", resizeMode: "contain", tintColor: "#3F3C42"}}/> <Image source={bracketRight} style={{width: 30, height: "100%", resizeMode: "contain", tintColor: colors.cardDetail}}/>
</Pressable> </Pressable>
</View> </View>
</LinearGradient> </LinearGradient>
@ -140,7 +199,7 @@ export default function RecipeSuggestion(props) {
)} )}
{visibleFilters &&( {visibleFilters &&(
<ScrollView> <ScrollView>
<LinearGradient colors={['#2680AA', '#59BDCD']} style={[styles.linearGradient, {paddingHorizontal: "3%"}]}> <LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {paddingHorizontal: "3%"}]}>
<View style={{marginTop: "10%"}}/> <View style={{marginTop: "10%"}}/>
<View style={styles.background}> <View style={styles.background}>
<View style={styles.filterBar}> <View style={styles.filterBar}>
@ -151,7 +210,7 @@ export default function RecipeSuggestion(props) {
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ListWithoutSelect title="Allergies" content={all}></ListWithoutSelect> <ListWithoutSelect title="Allergies" content={all}></ListWithoutSelect>
<View style={{marginTop: "3%"}}/> <View style={{marginTop: "3%"}}/>
<ValidateButton title="Add Allergy" image="plus.png" colour="#59BDCD" backColour="#E3DEC9"></ValidateButton> <ValidateButton title="Change Filters" image="update.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => props.navigation.navigate("FiltersSelection")}></ValidateButton>
</View> </View>
<View style={{marginTop: "6%"}}/> <View style={{marginTop: "6%"}}/>
<View> <View>
@ -167,76 +226,3 @@ export default function RecipeSuggestion(props) {
</SafeAreaProvider> </SafeAreaProvider>
); );
} }
const styles = StyleSheet.create({
linearGradient: {
width: "100%",
flex: 1,
//padding: "2%",
paddingTop: 0,
alignItems: "center",
justifyContent: "center"
},
background: {
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
borderRadius: 20,
backgroundColor: '#F2F0E4',
padding: "3%",
marginHorizontal: "3%",
},
filterBar: {
flexDirection: "row",
width: "85%",
paddingTop: "3%",
paddingBottom: "2%",
alignItems: "flex-end",
justifyContent: "center",
},
filters: {
fontSize: 20,
color: '#ACA279',
flex: 1,
},
nbSelected: {
fontSize: 11,
color: "#3F3C42",
textAlign: "right",
},
page: {
flex: 1,
backgroundColor: '#59BDCD',
alignItems: 'center',
paddingHorizontal: "3%",
},
modal :{
position: 'absolute',
top: '50%',
height: "50%",
width: "100%",
borderWidth: 1,
borderColor: "red",
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
},
horizontalAlignment: {
display: 'flex',
height: "10%",
width: "100%",
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
recipes: {
flexDirection: "row",
overflow: "scroll",
alignItems: "flex-start",
justifyContent: "center",
},
});

@ -3,8 +3,6 @@ const Alabaster = '#F2F0E4'
const Jet = '#3F3C42' const Jet = '#3F3C42'
const Moonstone = '#59BDCD' const Moonstone = '#59BDCD'
const Cerulean = '#2680AA' const Cerulean = '#2680AA'
const Celeste = '#ADF3EA'
const Tan = '#E0C293'
const Pearl = '#E3DEC9' const Pearl = '#E3DEC9'
const EerieBlack = '#222222' const EerieBlack = '#222222'
const CarolinaBlue = '#8DB4D9' const CarolinaBlue = '#8DB4D9'
@ -30,7 +28,15 @@ export interface Theme {
welcomeName: string, welcomeName: string,
carrouselBackground: string, carrouselBackground: string,
carrouselText: string, carrouselText: string,
carrouselDetail: string carrouselDetail: string,
textBottomBarFocussed: string,
blocBorder: string,
buttonMain: string,
yesButton: string,
letterFilter: string,
foodElementBorder: string,
badgeText: string,
recipeElementBackground: string,
} }
export const LightTheme : Theme = { export const LightTheme : Theme = {
@ -53,7 +59,15 @@ export const LightTheme : Theme = {
welcomeName: Moonstone, welcomeName: Moonstone,
carrouselBackground: Pearl, carrouselBackground: Pearl,
carrouselText: Ecru, carrouselText: Ecru,
carrouselDetail: Moonstone carrouselDetail: Moonstone,
textBottomBarFocussed: Moonstone,
blocBorder: Alabaster,
buttonMain: Ecru,
yesButton: Moonstone,
letterFilter: Moonstone,
foodElementBorder: Jet,
badgeText: Jet,
recipeElementBackground: Pearl,
} }
export const DarkTheme : Theme = { export const DarkTheme : Theme = {
@ -76,6 +90,14 @@ export const DarkTheme : Theme = {
welcomeName:Alabaster, welcomeName:Alabaster,
carrouselBackground: CarolinaBlue, carrouselBackground: CarolinaBlue,
carrouselText: SteelBlue, carrouselText: SteelBlue,
carrouselDetail: Alabaster carrouselDetail: Alabaster,
textBottomBarFocussed: SteelBlue,
blocBorder: EerieBlack,
buttonMain: CarolinaBlue,
yesButton: CarolinaBlue,
letterFilter: CarolinaBlue,
foodElementBorder: CarolinaBlue,
badgeText: Alabaster,
recipeElementBackground: Ecru,
} }

Loading…
Cancel
Save