recipe suggestion works

pull/23/head
Rayhân HASSOU 1 year ago
parent b98fe71167
commit 663c8bd799

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

@ -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<Recipes[]> {
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<Recipes[]>{
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);
}
}
}

@ -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 (
<Pressable style={styles.button} onPress={props.navigateDetails}>
<View style={styles.view}>
<Text style={styles.text}>{props.number}</Text>
<Text style={styles.title}>{props.title}</Text>
<Text style={styles.text}>{props.recipe.id}</Text>
<Text style={styles.title}>{props.recipe.name}</Text>
<Image source={brochette} style={{width: 100, resizeMode: "contain"}}/>
<View style={styles.horizontalAlignment}>
<Image source={Union_left} style={{width: "25%", marginRight: "3%", resizeMode: "contain"}} />
@ -87,8 +94,8 @@ export default function RecipeElement(props: RecipeElementProps) {
<Image source={Union_right} style={{ width: "25%", marginLeft: "3%", resizeMode: "contain"}} />
</View>
<View style={styles.horizontalAlignment}>
{props.textList.length > 0 && props.textList.map((source, index) => (
<Text key={index} style={styles.smallText}>- {source.title} -</Text>
{props.recipe.ingredients.length > 0 && props.recipe.ingredients.map((source, index) => (
<Text key={index} style={styles.smallText}>- {source.name} -</Text>
))}
</View>
<View style={styles.scrollViewContainer}>
@ -98,12 +105,14 @@ export default function RecipeElement(props: RecipeElementProps) {
<Image source={Union_right} style={{width: "27%", marginLeft: "3%", resizeMode: "contain"}}/>
</View>
<ScrollView style={{marginTop: "3%", overflow: "hidden"}}>
<Text style={styles.smallText}>{props.description}</Text>
<Text style={styles.smallText}>{props.recipe.description}</Text>
</ScrollView>
</View>
<Image source={background} style={{width: "80%", resizeMode: "contain", position: "absolute", zIndex: 1, top: "97.5%"}}></Image>
<Text style={styles.duration}>{props.duration}</Text>
<Text style={styles.duration}>{convertToHoursMinutes(props.recipe.time_to_cook)}</Text>
</View>
</Pressable>
);
}

@ -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) {
<Pressable onPress={decreaseCounter}>
<Image source={bracketLeft} style={{width: 40, height: 40, tintColor: colors.cardDetail, resizeMode: "contain"}}/>
</Pressable>
<FoodElementText title={props.ingredientList[cpt].title}/>
<FoodElementText title={props.ingredientList[cpt].name}/>
<Pressable onPress={increaseCounter}>
<Image source={bracketRight} style={{width: 40, height: 40, tintColor: colors.cardDetail, resizeMode: "contain"}}/>
</Pressable>

@ -15,7 +15,7 @@ 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 [isLoading, setIsLoading] = useState(true);
const [response, setResponse] = useState<Ingredient[] | undefined>(undefined);
const [selectedIngredients, setSelectedIngredients] = useState([]);
const [selectedIngredients, setSelectedIngredients] = useState<Ingredient[]>([]);
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 }) => (
<>
<View style={styles.horizontalAlignment}>
<Pressable onPress={() => SelectIngredient(value)}>
<FoodElementText title={value.name}/>
</Pressable>
<Pressable onPress={() => SelectIngredient(value)}>
<Image source={plus} style={{ width: 20, height: 20, tintColor: colors.cardDetail }} />
</Pressable>
@ -75,7 +77,9 @@ const loadIngredients = async () => {
const ChooseItem = ({ value }: { value: Ingredient }) => (
<>
<View style={styles.horizontalAlignment}>
<Pressable onPress={() => RemoveIngredient(value.id)}>
<FoodElementText title={value.name} />
</Pressable>
<Pressable onPress={() => RemoveIngredient(value.id)}>
<Image source={moins} style={{ width: 20, height: 20, tintColor: colors.cardDetail }} />
</Pressable>
@ -256,7 +260,12 @@ const loadIngredients = async () => {
</View>
</View>
<View style={{marginTop: "8%"}}></View>
<ValidateButton title="Find a recipe" image="validate.png" colour={colors.buttonMain} backColour={colors.cardBackground} todo={() => props.navigation.navigate("RecipeSuggestion")}/>
<ValidateButton title="Find a recipe" image="validate.png"
colour={colors.buttonMain}
backColour={colors.cardBackground}
todo={() => props.navigation.navigate('RecipeSuggestion',
{ingredients: selectedIngredients })}
/>
<View style={{marginBottom: "20%"}}></View>
</LinearGradient>
</SafeAreaProvider>

@ -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<Recipes[] | undefined>(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 ? (
<Text>No recipes</Text>
) : (
<View>
{selectedRecipes.map((recipe, index) => (
<View style={{ marginRight: 10 }} key={recipe.id}>
<RecipeElement
key={recipe.id}
recipe={recipe}
navigateDetails={goDetails}
/>
</View>
))}
</View>
);
const ingredientElements = limitedList.map((source, index) => (
<View style={[styles.horizontalAlignment, {marginVertical: "3%"}]}>
<FoodElementTextSimple title={source.title}/>
<View style={[styles.horizontalAlignment, {marginVertical: "3%"}]} key={index}>
<FoodElementTextSimple title={source.name}/>
<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")
const goDetails = () => navigation.navigate("RecipeDetails")
return (
<SafeAreaProvider style={{flex: 1}}>
@ -155,17 +209,11 @@ export default function RecipeSuggestion(props) {
<LinearGradient colors={[colors.primary, colors.primaryComplement]} style={[styles.linearGradient, {minHeight: useWindowDimensions().height}]}>
<View style={{marginTop: "6%"}}/>
<SelectedIngredient
ingredientList={ingredientList}
ingredientList={ingredients}
onEvent={handleChildEvent}/>
<ScrollView style={{ marginTop: "6%" }} horizontal={true}>
<View style={{ marginHorizontal: 10 }} />
<RecipeElement
number="63"
title="Meat Stick"
textList={ingredientList}
description="Delicious stick with 4 meats. Accessible for beginners. 20 min or less to cook."
duration="17 min"
navigateDetails={goDetails}/>
{recipeElements}
<View style={{ marginHorizontal: 10 }} />
</ScrollView>
<View style={{marginBottom: "20%"}}/>
@ -202,7 +250,7 @@ export default function RecipeSuggestion(props) {
<View style={{marginTop: "3%"}}/>
<ListWithoutSelect title="Allergies" content={all}></ListWithoutSelect>
<View style={{marginTop: "3%"}}/>
<ValidateButton title="Change Filters" image="update.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => props.navigation.navigate("FiltersSelection")}></ValidateButton>
<ValidateButton title="Change Filters" image="update.png" colour={colors.buttonDetail} backColour={colors.buttonBackground} todo={() => navigation.navigate("FiltersSelection")}></ValidateButton>
</View>
<View style={{marginTop: "6%"}}/>
<View>

Loading…
Cancel
Save