From 663c8bd79904211196fcd7cc381a00b7738a9a6d Mon Sep 17 00:00:00 2001 From: Rayhan Hassou Date: Tue, 5 Dec 2023 13:26:15 +0100 Subject: [PATCH] recipe suggestion works --- .../Services/Recipes/IRecipesServices.tsx | 1 + .../Services/Recipes/RecipesServices.tsx | 17 +++- LeftOvers/components/RecipeElement.tsx | 31 +++--- LeftOvers/components/SelectedIngredient.tsx | 5 +- LeftOvers/screens/IngredientSelection.tsx | 17 +++- LeftOvers/screens/RecipeSuggestion.tsx | 96 ++++++++++++++----- 6 files changed, 124 insertions(+), 43 deletions(-) diff --git a/LeftOvers/Services/Recipes/IRecipesServices.tsx b/LeftOvers/Services/Recipes/IRecipesServices.tsx index 6585cab..2952d00 100644 --- a/LeftOvers/Services/Recipes/IRecipesServices.tsx +++ b/LeftOvers/Services/Recipes/IRecipesServices.tsx @@ -3,4 +3,5 @@ import Recipes from "../../Models/Recipes"; export default interface IRecipesService { getAllRecipes(): Promise; getRecipeById(id: number): Promise; + getRecipeWithIngredients(ids: string[]): Promise; } \ No newline at end of file diff --git a/LeftOvers/Services/Recipes/RecipesServices.tsx b/LeftOvers/Services/Recipes/RecipesServices.tsx index e5100ba..ee24380 100644 --- a/LeftOvers/Services/Recipes/RecipesServices.tsx +++ b/LeftOvers/Services/Recipes/RecipesServices.tsx @@ -4,13 +4,14 @@ import Recipes from "../../Models/Recipes"; export default class RecipesService implements IRecipesService { private readonly API_URL = "http://leftovers.alwaysdata.net/recipes"; + private readonly IA_URL = "https://codefirst.iut.uca.fr/containers/Sae_LeftOvers-leftovers_ia/getrecipes" async getAllRecipes(): Promise { try { const response = await axios.get(this.API_URL); return response.data as Recipes[]; } 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 recettes dans getAllRecipes: ' + error.message); } } @@ -21,8 +22,20 @@ export default class RecipesService implements IRecipesService { //console.log(response.name); return response.data as Recipes; } 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 recettes dans getRecipeById : ' + error.message); } } + async getRecipeWithIngredients(ids: string[]): Promise{ + const recipe: Recipes[] = []; + try { + const response = await axios.get(`${this.IA_URL}/${ids}`); + if(response == null){ + return recipe; + } + return response.data as Recipes[]; + } catch (error) { + throw new Error('Erreur lors de la récupération des recettes dans getRecipeWithIngredients : ' + error.message); + } + } } diff --git a/LeftOvers/components/RecipeElement.tsx b/LeftOvers/components/RecipeElement.tsx index 2a37a42..8a17313 100644 --- a/LeftOvers/components/RecipeElement.tsx +++ b/LeftOvers/components/RecipeElement.tsx @@ -5,16 +5,23 @@ import Union_left from '../assets/images/Union_left.png'; import Union_right from '../assets/images/Union_right.png'; import background from '../assets/images/Background.png'; import ColorContext from '../theme/ColorContext'; +import Recipes from '../Models/Recipes'; interface RecipeElementProps { - number: string - title: string - textList: {title: string}[] - description: string - duration: string + recipe: Recipes navigateDetails: () => void } +function convertToHoursMinutes(totalMinutes: number): string { + const hours = Math.floor(totalMinutes / 60); + const minutes = totalMinutes % 60; + + const hoursString = hours > 0 ? `${hours} h` : ''; + const minutesString = minutes > 0 ? ` ${minutes} min` : ''; + + return `${hoursString}${minutesString}`.trim(); +} + export default function RecipeElement(props: RecipeElementProps) { const {colors} = useContext(ColorContext) @@ -78,8 +85,8 @@ export default function RecipeElement(props: RecipeElementProps) { return ( - {props.number} - {props.title} + {props.recipe.id} + {props.recipe.name} @@ -87,8 +94,8 @@ export default function RecipeElement(props: RecipeElementProps) { - {props.textList.length > 0 && props.textList.map((source, index) => ( - - {source.title} - + {props.recipe.ingredients.length > 0 && props.recipe.ingredients.map((source, index) => ( + - {source.name} - ))} @@ -98,12 +105,14 @@ export default function RecipeElement(props: RecipeElementProps) { - {props.description} + {props.recipe.description} - {props.duration} + {convertToHoursMinutes(props.recipe.time_to_cook)} ); + + } \ No newline at end of file diff --git a/LeftOvers/components/SelectedIngredient.tsx b/LeftOvers/components/SelectedIngredient.tsx index ac5dfe4..6f129de 100644 --- a/LeftOvers/components/SelectedIngredient.tsx +++ b/LeftOvers/components/SelectedIngredient.tsx @@ -5,9 +5,10 @@ import bracketRight from '../assets/images/angle_bracket_right.png'; import parameter from '../assets/images/parameter.png'; import FoodElementText from './FoodElementText'; import ColorContext from '../theme/ColorContext'; +import Ingredient from '../Models/Ingredient'; interface SelectedIngredientProps { - ingredientList: {title: string}[] + ingredientList: Ingredient[] onEvent: () => void } @@ -72,7 +73,7 @@ export default function SelectedIngredient(props: SelectedIngredientProps) { - + diff --git a/LeftOvers/screens/IngredientSelection.tsx b/LeftOvers/screens/IngredientSelection.tsx index ee7b49a..8ef1e21 100644 --- a/LeftOvers/screens/IngredientSelection.tsx +++ b/LeftOvers/screens/IngredientSelection.tsx @@ -15,7 +15,7 @@ export default function IngredientSelection(props) { const alphabetArray: Array = ["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 [response, setResponse] = useState(undefined); - const [selectedIngredients, setSelectedIngredients] = useState([]); + const [selectedIngredients, setSelectedIngredients] = useState([]); const ingredientService = new IngredientService(); const {colors} = useContext(ColorContext); const [availableSize, setAvailableSize] = useState(0); @@ -63,7 +63,9 @@ const loadIngredients = async () => { const AvailableItem = ({ value }: { value: Ingredient }) => ( <> - + SelectIngredient(value)}> + + SelectIngredient(value)}> @@ -75,7 +77,9 @@ const loadIngredients = async () => { const ChooseItem = ({ value }: { value: Ingredient }) => ( <> - + RemoveIngredient(value.id)}> + + RemoveIngredient(value.id)}> @@ -256,7 +260,12 @@ const loadIngredients = async () => { - props.navigation.navigate("RecipeSuggestion")}/> + props.navigation.navigate('RecipeSuggestion', + {ingredients: selectedIngredients })} + /> diff --git a/LeftOvers/screens/RecipeSuggestion.tsx b/LeftOvers/screens/RecipeSuggestion.tsx index d6bfa1a..ff46ac0 100644 --- a/LeftOvers/screens/RecipeSuggestion.tsx +++ b/LeftOvers/screens/RecipeSuggestion.tsx @@ -1,4 +1,4 @@ -import React, { useState, useContext } from 'react'; +import React, { useState, useContext, useEffect } from 'react'; import {View, StyleSheet, Text, Image, Pressable, useWindowDimensions, ScrollView} from 'react-native'; import {SafeAreaProvider } from 'react-native-safe-area-context'; import {Modal, Portal, PaperProvider} from 'react-native-paper'; @@ -15,24 +15,35 @@ import bracketLeft from '../assets/images/angle_bracket_left.png'; import bracketRight from '../assets/images/angle_bracket_right.png'; import plus from '../assets/images/plus_small.png'; import minus from '../assets/images/minus.png'; +import { useNavigation } from '@react-navigation/native'; +import RecipesServices from '../Services/Recipes/RecipesServices'; +import Recipes from '../Models/Recipes'; +import Ingredient from '../Models/Ingredient'; -export default function RecipeSuggestion(props) { +export default function RecipeSuggestion({ route }) { const {colors} = useContext(ColorContext) const [visible, setVisible] = React.useState(false); const [visibleFilters, setVisibleFilters] = React.useState(false); const [visibleIngredients, setVisibleIngredients] = React.useState(true); const [minCpt, setMinCpt] = useState(0); const [maxCpt, setMaxCpt] = useState(4); - const ingredientList = [{title: "Steak"}, {title: "Sheep Ribs"}, {title: "Rabbit Thigh"}, {title: "Ham"}, {title: "Cream (Liquid)"}, {title: "Pepper Bell"}] - const ingredientListV2 = [{title: "Smoked Salmon"}, {title: "Tomato"}, {title: "Carrot"}] - const limitedList = ingredientList.slice(minCpt, maxCpt); const [colorIngredients, setColorIngredients] = useState("#59BDCD"); const [colorFilters, setColorFilters] = useState(colors.cardDetail); + const [isLoading, setIsLoading] = useState(true); + const [response, setResponse] = useState(undefined); + const [selectedRecipes, setSelectedRecipes] = useState([]); + console.log(selectedRecipes); + const recipeService = new RecipesServices(); + const { ingredients } = route.params; + const limitedList = ingredients.slice(minCpt, maxCpt); + let selectedIngredients: string[]; + const navigation = useNavigation(); const die = [{value: "Gluten free"}, {value: "Porkless"}, {value: "Gluten free"}, {value: "Porkless"}] const all = [] + const containerStyle = { //minHeight: useWindowDimensions().height/2, //width: useWindowDimensions().width, @@ -64,13 +75,13 @@ export default function RecipeSuggestion(props) { setMaxCpt(maxCpt - 4) } else{ - setMaxCpt(ingredientList.length+ingredientList.length%4) - let cpt=ingredientList.length-(ingredientList.length%4) + setMaxCpt(ingredients.length+ingredients.length%4) + let cpt=ingredients.length-(ingredients.length%4) setMinCpt(cpt) } } const increaseCounter = () => { - if (maxCpt < ingredientList.length) { + if (maxCpt < ingredients.length) { setMinCpt(minCpt + 4); setMaxCpt(maxCpt + 4) } @@ -79,6 +90,33 @@ export default function RecipeSuggestion(props) { setMaxCpt(4) } } + const getIngredientsIds = (ingredients) => { + console.log("Liste des ingredients : " + ingredients[0].name) + selectedIngredients = ingredients.map(ingredient => ingredient.id).join(':'); + return selectedIngredients; + }; + + const loadRecipes = async () => { + const ids: string[] = getIngredientsIds(ingredients); + console.log("Les ids des ingredients : " + ids); + try { + const recipes: Recipes[] = await recipeService.getRecipeWithIngredients(ids); + console.log("Les recettes trouvé : " + recipes) + if(recipes === null){ + setSelectedRecipes(recipes); + } + + } catch (error) { + console.log(error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + console.log("Je passe ici (Ingredient Selection)") + loadRecipes(); + }, []); const styles = StyleSheet.create({ linearGradient: { @@ -138,15 +176,31 @@ export default function RecipeSuggestion(props) { }, }); + const recipeElements = Array.isArray(selectedRecipes) && selectedRecipes.length === 0 ? ( + No recipes + ) : ( + + {selectedRecipes.map((recipe, index) => ( + + + + ))} + + ); + const ingredientElements = limitedList.map((source, index) => ( - - + + )); - const goDetails = () => props.navigation.navigate("RecipeDetails") + const goDetails = () => navigation.navigate("RecipeDetails") return ( @@ -155,19 +209,13 @@ export default function RecipeSuggestion(props) { - - - - - + + + {recipeElements} + + @@ -202,7 +250,7 @@ export default function RecipeSuggestion(props) { - props.navigation.navigate("FiltersSelection")}> + navigation.navigate("FiltersSelection")}>