diff --git a/.drone.yml b/.drone.yml index 7f1dcbe..29b8fb3 100644 --- a/.drone.yml +++ b/.drone.yml @@ -12,7 +12,8 @@ steps: commands: - cd ./LeftOvers/ - npm install - - npm run + - npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/res/raw/index.android.bundle --assets-dest android/app/src/main/res/ + - name: code-analysis image: node:latest diff --git a/LeftOvers/Models/Profile.tsx b/LeftOvers/Models/Profile.tsx new file mode 100644 index 0000000..1dc1775 --- /dev/null +++ b/LeftOvers/Models/Profile.tsx @@ -0,0 +1,30 @@ +export default class Profile { + private _name: string; + private _avatar: string; + private _allergy: string[]; + private _diets: string[]; + + constructor( name: string, avatar: string, allergy: string[], diets: string[]) { + this._name = name; + this._avatar = avatar; + this._allergy = allergy; + this._diets = diets; + } + + get name(): string { + return this._name; + } + + + get avatar(): string{ + return this._avatar; + } + + get allergy(): string[]{ + return this._allergy; + } + + get diets(): string[]{ + return this._diets; + } + } \ No newline at end of file diff --git a/LeftOvers/Services/Profiles/IProfileService.ts b/LeftOvers/Services/Profiles/IProfileService.ts new file mode 100644 index 0000000..425a961 --- /dev/null +++ b/LeftOvers/Services/Profiles/IProfileService.ts @@ -0,0 +1,7 @@ +import Profil from "../../Models/Profil"; + +export default interface IProfileService { + getProfiles(): Promise, + addProfile(new_profile: Profil): Promise, + delProfile(profile_name_to_del: string): Promise +} \ No newline at end of file diff --git a/LeftOvers/Services/Profiles/ProfileService.ts b/LeftOvers/Services/Profiles/ProfileService.ts new file mode 100644 index 0000000..30646bf --- /dev/null +++ b/LeftOvers/Services/Profiles/ProfileService.ts @@ -0,0 +1,41 @@ +import Profil from "../../Models/Profil"; +import IProfileService from "./IProfileService"; +import AsyncStorage from "@react-native-async-storage/async-storage"; + +export default class ProfileService implements IProfileService { + async getProfiles(): Promise { + const results = await AsyncStorage.getItem('profiles'); + const tmp = JSON.parse(results) + let existingProfiles: Profil[] = [] + for (let item of tmp) { + existingProfiles.push(new Profil(item._name, item._avatar, item._allergy, item._diets)) + } + return existingProfiles; + } + + async addProfile(new_profile : Profil): Promise { + const existingProfiles = await this.getProfiles() + for (let current_profile of existingProfiles) { + if (current_profile.name == new_profile.name) { + console.log("Tried to create a profil already existing !") + return false + } + } + await AsyncStorage.setItem('profiles', JSON.stringify([...existingProfiles, new_profile])) + return true + } + + async delProfile(profile_name_to_del: string): Promise { + const existing_profiles = await this.getProfiles() + let key: number = -1 + for (let current_profile of existing_profiles) { + if (current_profile.name == profile_name_to_del) { + let updated_profile = existing_profiles.splice(key, 1) + await AsyncStorage.setItem('profiles', JSON.stringify(updated_profile)) + return true + } + key ++ + } + return false + } +} \ No newline at end of file diff --git a/LeftOvers/Services/Recipes/RecipesServices.tsx b/LeftOvers/Services/Recipes/RecipesServices.tsx index 49bd8c4..496aef4 100644 --- a/LeftOvers/Services/Recipes/RecipesServices.tsx +++ b/LeftOvers/Services/Recipes/RecipesServices.tsx @@ -19,7 +19,6 @@ export default class RecipesService implements IRecipesService { async getRecipeById(id: number): Promise{ try { const response = await axios.get(`${this.API_URL}/${id}`); - //console.log(response.name); return response.data as Recipes; } catch (error) { throw new Error('Erreur lors de la récupération des recettes dans getRecipeById : ' + error.message); diff --git a/LeftOvers/android/app/src/main/res/raw/placeholder.txt b/LeftOvers/android/app/src/main/res/raw/placeholder.txt new file mode 100644 index 0000000..e69de29 diff --git a/LeftOvers/components/FoodElementText.tsx b/LeftOvers/components/FoodElementText.tsx index 006abc8..abd64a1 100644 --- a/LeftOvers/components/FoodElementText.tsx +++ b/LeftOvers/components/FoodElementText.tsx @@ -14,8 +14,8 @@ const componentHeight = 60; const componentWidth = 280; -export default function FoodElementText(props : any) { - const {colors} = useContext(ColorContext) +export default function FoodElementText(props : FoodElementTextProps) { + const colors = useContext(ColorContext).colors const styles = StyleSheet.create({ button: { @@ -37,11 +37,12 @@ export default function FoodElementText(props : any) { alignItems: 'flex-start', justifyContent: 'center', marginRight: "3%", + marginBottom: "2%", width: "100%" }, container: { width: "100%", - height: 50, + //height: 50, borderRadius: 5, borderWidth: 2, borderColor: props.secondaryColour ? props.secondaryColour : colors.foodElementBorder, diff --git a/LeftOvers/components/ListSelect.tsx b/LeftOvers/components/ListSelect.tsx index 24bf043..5a2e9e2 100644 --- a/LeftOvers/components/ListSelect.tsx +++ b/LeftOvers/components/ListSelect.tsx @@ -1,6 +1,6 @@ import React, { useContext } from 'react'; -import {StyleSheet, Image} from 'react-native'; -import {MultipleSelectList} from 'react-native-dropdown-select-list' +import { StyleSheet, Image } from 'react-native'; +import { MultipleSelectList } from 'react-native-dropdown-select-list' import ColorContext from '../theme/ColorContext'; type ListProps = { @@ -11,8 +11,7 @@ type ListProps = { } export default function ListSelect(props: ListProps) { - - const {colors} = useContext(ColorContext); + const colors = useContext(ColorContext).colors; const styles = StyleSheet.create({ titleBar: { diff --git a/LeftOvers/components/ListWithoutSelect.tsx b/LeftOvers/components/ListWithoutSelect.tsx index 1944867..a095f3c 100644 --- a/LeftOvers/components/ListWithoutSelect.tsx +++ b/LeftOvers/components/ListWithoutSelect.tsx @@ -1,6 +1,6 @@ import React, { useContext } from 'react'; -import {StyleSheet, Image} from 'react-native'; -import {MultipleSelectList} from 'react-native-dropdown-select-list' +import { StyleSheet, Image } from 'react-native'; +import { MultipleSelectList } from 'react-native-dropdown-select-list' import ColorContext from '../theme/ColorContext'; type ListProps = { @@ -10,8 +10,7 @@ type ListProps = { export default function ListWithoutSelect(props: ListProps) { const [selected, setSelected] = React.useState([]); - const { colors } = useContext(ColorContext); - + const colors = useContext(ColorContext).colors; const styles = StyleSheet.create({ titleBar: { diff --git a/LeftOvers/components/ProfileDetails.tsx b/LeftOvers/components/ProfileDetails.tsx index c372b11..750c48c 100644 --- a/LeftOvers/components/ProfileDetails.tsx +++ b/LeftOvers/components/ProfileDetails.tsx @@ -14,7 +14,7 @@ type ProfileProps = { } export default function ProfileDetails(props) { - const { colors } = useContext(ColorContext) + const colors = useContext(ColorContext).colors const [display, setDisplay] = useState("none") const changeListVisibility = () => { if (display == "none"){ @@ -26,15 +26,11 @@ export default function ProfileDetails(props) { }; let imageSource - - if (props.avatar === "plus.png"){ - imageSource = require('../assets/images/plus.png') - } - else if (props.avatar === "plus_small.png"){ - imageSource = require('../assets/images/plus_small.png') + if (props.avatar == ""){ + imageSource = require("../assets/images/logo.png") } else{ - imageSource = require('../assets/images/logo.png') + imageSource = {uri: props.avatar} } const styles = StyleSheet.create({ @@ -139,7 +135,7 @@ export default function ProfileDetails(props) { Filters - {props.diets.length} diets selected + {/*{props.diets.length} diets selected*/} diff --git a/LeftOvers/components/ProfileElement.tsx b/LeftOvers/components/ProfileElement.tsx index e78d8e0..2f4f0d9 100644 --- a/LeftOvers/components/ProfileElement.tsx +++ b/LeftOvers/components/ProfileElement.tsx @@ -10,7 +10,7 @@ type Profile = { } export default function ProfileElement(props : Profile) { - const { colors } = useContext(ColorContext) + const colors = useContext(ColorContext).colors const [waiting, setWaiting] = useState("none") const [separator, setSeparator] = useState("none") @@ -36,12 +36,11 @@ export default function ProfileElement(props : Profile) { } let imageSource - if(props.avatar == null){ - console.log("NUUUULLLLLE" + props.avatar) + if(props.avatar == ""){ + imageSource=require("../assets/images/logo.png") } else{ imageSource = { uri: props.avatar }; - console.log("MAAARCHHEEE" + props.avatar) } const styles = StyleSheet.create({ diff --git a/LeftOvers/components/ProfileModification.tsx b/LeftOvers/components/ProfileModification.tsx index d738e9a..11c4527 100644 --- a/LeftOvers/components/ProfileModification.tsx +++ b/LeftOvers/components/ProfileModification.tsx @@ -15,7 +15,7 @@ type ProfileProps = { export default function ProfileModification(props: ProfileProps) { const [name, onChangeName] = useState(props.name); - const { colors } = useContext(ColorContext); + const colors = useContext(ColorContext).colors; let imageSource if (props.avatar == "plus.png"){ diff --git a/LeftOvers/components/ProfileSelection.tsx b/LeftOvers/components/ProfileSelection.tsx index 376ee7e..daf409e 100644 --- a/LeftOvers/components/ProfileSelection.tsx +++ b/LeftOvers/components/ProfileSelection.tsx @@ -19,7 +19,7 @@ type Profile = { } export default function ProfileSelection(props: ProfileSelectionProps) { - const { colors } = useContext(ColorContext); + const colors = useContext(ColorContext).colors; const [cpt, setCpt] = useState(0); const decreaseCounter = () => { diff --git a/LeftOvers/components/RecipeElementReduce.tsx b/LeftOvers/components/RecipeElementReduce.tsx index 7ee1da4..bea510c 100644 --- a/LeftOvers/components/RecipeElementReduce.tsx +++ b/LeftOvers/components/RecipeElementReduce.tsx @@ -1,7 +1,8 @@ -import React from 'react'; +import React, {useContext} from 'react'; import {StyleSheet, Text, View, Image} from 'react-native'; import brochette from '../assets/images/brochette.png'; -import background from '../assets/images/Background.png'; +import background from '../assets/images/Background.png'; +import ColorContext from '../theme/ColorContext'; interface RecipeElementReduceProps { @@ -12,6 +13,53 @@ interface RecipeElementReduceProps { } export default function RecipeElementReduce(props: RecipeElementReduceProps) { + const {colors} = useContext(ColorContext) + + const styles = StyleSheet.create({ + button: { + alignItems: 'center', + justifyContent: 'center', + width : 250, + height: 250, + borderRadius: 40, + backgroundColor: colors.recipeElementBackground, + }, + text: { + fontSize: 15, + fontWeight: 'bold', + color: '#6F6532', + marginTop: "4%", + zIndex: 2 + }, + smallText: { + position: "absolute", + fontSize: 12, + color: '#F2F0E4', + textAlign: "center", + margin : "2%", + zIndex: 2, + fontWeight: "bold", + top: "89.25%" + }, + title:{ + fontSize: 18, + fontWeight: 'bold', + color: '#524B1A', + zIndex: 2 + }, + view: { + width : "95%", + height: "95%", + borderRadius: 40, + borderWidth: 2, + padding: "5%", + borderColor: '#73692A', + alignItems: 'center', + justifyContent: "center", + }, + }); + + return ( @@ -24,49 +72,4 @@ export default function RecipeElementReduce(props: RecipeElementReduceProps) { ); -} - - -const styles = StyleSheet.create({ - button: { - alignItems: 'center', - justifyContent: 'center', - width : 250, - height: 250, - borderRadius: 40, - backgroundColor: '#E3DEC9', - }, - text: { - fontSize: 15, - fontWeight: 'bold', - color: '#756C28', - marginTop: "4%", - zIndex: 2 - }, - smallText: { - position: "absolute", - fontSize: 12, - color: '#F2F0E4', - textAlign: "center", - margin : "2%", - zIndex: 2, - fontWeight: "bold", - top: "89.25%" - }, - title:{ - fontSize: 18, - fontWeight: 'bold', - color: '#524B1A', - zIndex: 2 - }, - view: { - width : "95%", - height: "95%", - borderRadius: 40, - borderWidth: 2, - padding: "5%", - borderColor: '#73692A', - alignItems: 'center', - justifyContent: "center", - }, -}); \ No newline at end of file +} \ No newline at end of file diff --git a/LeftOvers/navigation/BottomBar.tsx b/LeftOvers/navigation/BottomBar.tsx index c2484bf..a65c78d 100644 --- a/LeftOvers/navigation/BottomBar.tsx +++ b/LeftOvers/navigation/BottomBar.tsx @@ -15,7 +15,7 @@ import DarkIcon from '../assets/images/moon.png'; export default function BottomBar({ state, descriptors, navigation }) { const {theme, toggleTheme} = useContext(ThemeContext); - const {colors, toggleColors} = useContext(ColorContext) + const { colors, toggleColors } = useContext(ColorContext); const [iconThemeButton, setThemeIconButton] = useState(( theme === 'dark' ) ? LightIcon : DarkIcon) const [textThemeButton, setTextThemeButton] = useState(( theme === 'dark' ) ? 'Light' : 'Dark'); @@ -47,10 +47,10 @@ export default function BottomBar({ state, descriptors, navigation }) { flexDirection: 'row', alignItems: 'center', alignContent: 'space-around', - borderBlockColor: theme === 'light' ? '#F2F0E4' : '#222222', + borderBlockColor: colors.blocBorder, borderWidth: 2, - borderLeftColor: theme === 'light'? '#F2F0E4' : '#222222', - borderRightColor: theme === 'light'? '#F2F0E4' : '#222222', + borderLeftColor: colors.blocBorder, + borderRightColor: colors.blocBorder, }, BottomBarIcon: { width: 25, diff --git a/LeftOvers/navigation/CookingStackScreen.tsx b/LeftOvers/navigation/CookingStackScreen.tsx index 669a8b2..978c45e 100644 --- a/LeftOvers/navigation/CookingStackScreen.tsx +++ b/LeftOvers/navigation/CookingStackScreen.tsx @@ -1,5 +1,4 @@ import React, { useContext } from 'react' -import { StyleSheet } from 'react-native' import { createNativeStackNavigator } from '@react-navigation/native-stack'; import IngredientSelection from '../screens/IngredientSelection'; @@ -11,7 +10,7 @@ import RecipeDetails from '../screens/RecipeDetails'; const CookingStack = createNativeStackNavigator() export default function CookingStackScreen() { - const {theme} = useContext(ThemeContext); + const theme = useContext(ThemeContext).theme; return ( @@ -47,10 +46,4 @@ export default function CookingStackScreen() { /> ) -} - -const styles = StyleSheet.create({ - headerBarContainer: { - backgroundColor: '#F2F0E4', - }, -}) \ No newline at end of file +} \ No newline at end of file diff --git a/LeftOvers/navigation/HomeStackScreen.tsx b/LeftOvers/navigation/HomeStackScreen.tsx index 512369d..4f9c293 100644 --- a/LeftOvers/navigation/HomeStackScreen.tsx +++ b/LeftOvers/navigation/HomeStackScreen.tsx @@ -25,7 +25,7 @@ function AppIcon() { } export default function HomeStackScreen() { - const {colors} = useContext(ColorContext) + const colors = useContext(ColorContext).colors return ( diff --git a/LeftOvers/navigation/ProfileStackScreen.tsx b/LeftOvers/navigation/ProfileStackScreen.tsx index 8a725c5..d1ccaff 100644 --- a/LeftOvers/navigation/ProfileStackScreen.tsx +++ b/LeftOvers/navigation/ProfileStackScreen.tsx @@ -5,7 +5,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack'; 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 { HeaderTitle } from './Utils'; @@ -15,11 +15,11 @@ import AddIcon from '../assets/images/plus.png' const ProfilesStack = createNativeStackNavigator() export default function ProfilesStackScreen({ navigation }) { - const {theme} = useContext(ThemeContext); + const colors = useContext(ColorContext).colors; const styles = StyleSheet.create({ headerBarContainer: { - backgroundColor: theme === 'light' ? '#F2F0E4' : '#3F3C42', + backgroundColor: colors.cardBackground, }, headerBarRightContainer: { display: 'flex', @@ -55,13 +55,13 @@ export default function ProfilesStackScreen({ navigation }) { + tintColor={colors.cardDetail}/> + tintColor={colors.cardDetail}/> ) diff --git a/LeftOvers/navigation/Utils.tsx b/LeftOvers/navigation/Utils.tsx index 557d67b..4a3a9bc 100644 --- a/LeftOvers/navigation/Utils.tsx +++ b/LeftOvers/navigation/Utils.tsx @@ -4,7 +4,7 @@ import { Text, StyleSheet } from 'react-native'; import ColorContext from '../theme/ColorContext'; export function HeaderTitle(props) { - const {colors} = useContext(ColorContext) + const colors = useContext(ColorContext).colors const styles = StyleSheet.create({ headerTitle: { diff --git a/LeftOvers/screens/CreateProfile.tsx b/LeftOvers/screens/CreateProfile.tsx index 8e6a161..72a37c7 100644 --- a/LeftOvers/screens/CreateProfile.tsx +++ b/LeftOvers/screens/CreateProfile.tsx @@ -1,23 +1,24 @@ import React, { useContext, useState } from 'react'; -import {StyleSheet, View, ScrollView, useWindowDimensions, TextInput, Image, Text, NativeEventEmitter, Pressable} from 'react-native'; +import {StyleSheet, View, ScrollView, useWindowDimensions, TextInput, Image, Text, Pressable} from 'react-native'; import { LinearGradient } from 'expo-linear-gradient'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import ValidateButton from '../components/ValidateButton'; 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'; +import AsyncStorage from '@react-native-async-storage/async-storage'; export default function CreateProfile(props) { - const { colors } = useContext(ColorContext) + const colors = useContext(ColorContext).colors const all = [] const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}] const [name, onChangeName] = useState(); const [avatar, setAvatar] = useState(''); const [selectedDiets, setSelectedDiets] = useState([]); + const [selectedAllergies] = useState([]) const handleSelectedDiets = (selectedValues) => { setSelectedDiets(selectedValues); @@ -26,26 +27,23 @@ export default function CreateProfile(props) { 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, + mediaTypes: ImagePicker.MediaTypeOptions.All, + allowsEditing: true, + aspect: [4, 3], + quality: 1, }); console.log(result); if (!result.canceled) { - setAvatar(result.assets[0].uri); + 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} + if (props.avatar == ""){ + imageSource = require("../assets/images/logo.png") } else{ imageSource = {uri: avatar} @@ -59,6 +57,7 @@ export default function CreateProfile(props) { avatar: avatar, diets: selectedDiets, allergies: all, + isActive: "flex", }; // Mettre à jour AsyncStorage avec le nouveau profil @@ -67,14 +66,10 @@ export default function CreateProfile(props) { const updatedProfiles = [...existingProfiles, newProfile]; await AsyncStorage.setItem('profiles', JSON.stringify(updatedProfiles)); EventEmitter.emit('profileAdded'); - console.log('Profil créé :', newProfile); - props.navigation.goBack(); - - alert('Profil créé !'); } catch (error) { - console.error('Erreur lors de la création du profil :', error); + console.error('Erreur lors de la création du profil :', error); } }; @@ -112,6 +107,7 @@ export default function CreateProfile(props) { borderColor: colors.cardElementBorder, borderRadius: 45, height: "100%", + minHeight: 35, flex: 0.04, }, textInput: { @@ -169,11 +165,10 @@ export default function CreateProfile(props) { Filters - "0 diets selected - + diff --git a/LeftOvers/screens/HomePage.tsx b/LeftOvers/screens/HomePage.tsx index 73f4e2e..697dd82 100644 --- a/LeftOvers/screens/HomePage.tsx +++ b/LeftOvers/screens/HomePage.tsx @@ -12,20 +12,18 @@ import bracketLeft from '../assets/images/angle_bracket_left.png'; import bracketRight from '../assets/images/angle_bracket_right.png'; import AsyncStorage from '@react-native-async-storage/async-storage'; -import EventEmitter from './EventEmitter'; +import EventEmitter from './EventEmitter'; export default function HomePage({ navigation, props }) { - const {colors} = useContext(ColorContext); + const colors = useContext(ColorContext).colors const profilesHand = [ - {name: "Johnny Silverhand", avatar: "plus_small.png", isActive: "flex"}, - {name: "Panam Palmer", avatar: "plus_small.png", isActive: "none"}, - {name: "Goro Takemura", avatar: "plus_small.png", isActive: "none"}, - {name: "David Martinez", avatar: "plus_small.png", isActive: "flex"}, + {name: "None", avatar: "logo.png", isActive: "none"} ] + const ingredientListHand = [{name: "None"}] - const [profiles, setProfiles] = useState([{name: "None", avatar: "plus_small.png", isActive: "none"}]); - console.log(profiles, profiles.length) + const [profiles, setProfiles] = useState(profilesHand); + const [ingredientList, setIngredientList] = useState(ingredientListHand) const handleGetProfiles = async () => { try { @@ -37,27 +35,71 @@ export default function HomePage({ navigation, props }) { } } + const handleGetAvailableIngredient = async () => { + try { + const existingAvailableIngredient = await AsyncStorage.getItem('ingredient'); + return JSON.parse(existingAvailableIngredient) || []; + } catch (error) { + console.log(error); + return []; + } + } + const fetchProfiles = async () => { const existingProfiles = await handleGetProfiles(); - setProfiles(existingProfiles); + if (existingProfiles.length != 0){ + setProfiles(existingProfiles); + } + else{ + setProfiles(profilesHand) + } + }; + + const fetchAvailableIngredient = async () => { + const existingAvailableIngredient = await handleGetAvailableIngredient(); + if (existingAvailableIngredient.length != 0){ + setIngredientList(existingAvailableIngredient); + } + else{ + setIngredientList(ingredientListHand) + } }; - const subscription = EventEmitter.addListener('profileAdded', async () => { + const subscriptionAddProfile = EventEmitter.addListener('profileAdded', async () => { fetchProfiles(); }); + const subscriptionDeleteProfile = EventEmitter.addListener('profileDeleted', async () => { + if (profiles.length == 1){ + setProfiles(profilesHand) + } + else{ + fetchProfiles(); + } + }); + + const subscriptionAddIngredient = EventEmitter.addListener('ingredientAdded', async () => { + fetchAvailableIngredient(); + }); + + const subscriptionDeleteIngredient = EventEmitter.addListener('ingredientDeleted', async () => { + if (ingredientList.length == 1){ + setIngredientList(ingredientListHand) + } + else{ + fetchAvailableIngredient(); + } + }); + useEffect(() => { + //AsyncStorage.clear() fetchProfiles(); - console.log(profiles.length) if(profiles.length == 0){ setProfiles([{name: "None", avatar: "plus_small.png", isActive: "none"}]) - console.log("Je passe ici") } - console.log(profiles) + fetchAvailableIngredient(); }, []); - const ingredientList = [{title: "Carrot"}, {title: "Potato"}, {title: "Peach"}] - const [cpt, setCpt] = useState(0); const decreaseCounter = () => { if (cpt > 0) { @@ -157,8 +199,8 @@ export default function HomePage({ navigation, props }) { const nbActiveProfiles = () => { let cpt = 0 - profiles.forEach((val) => { - if(val.isActive == "flex"){ + profiles.forEach((profile) => { + if(profile.isActive == "flex"){ cpt += 1 } }) @@ -205,16 +247,16 @@ export default function HomePage({ navigation, props }) { - + - console.log('Chnge Selected Ingredient')}/> + navigation.navigate("IngredientSelection")}/> - console.log('Go and search for recipe')}/> + navigation.navigate("RecipeSuggestion")}/> diff --git a/LeftOvers/screens/IngredientSelection.tsx b/LeftOvers/screens/IngredientSelection.tsx index 490e587..e3ca9b9 100644 --- a/LeftOvers/screens/IngredientSelection.tsx +++ b/LeftOvers/screens/IngredientSelection.tsx @@ -2,22 +2,27 @@ import React, { useEffect, useState, useContext } from 'react'; import { View, StyleSheet, Text, Image, Pressable, ActivityIndicator, FlatList, useWindowDimensions } from 'react-native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { Searchbar } from 'react-native-paper'; +import { LinearGradient } from 'expo-linear-gradient'; + import FoodElementText from '../components/FoodElementText'; -import plus from '../assets/images/plus.png'; -import moins from '../assets/images/minus.png'; import Ingredient from '../Models/Ingredient'; import IngredientService from '../Services/Ingredients/IngredientsServices'; -import { LinearGradient } from 'expo-linear-gradient'; import ColorContext from '../theme/ColorContext'; import ValidateButton from '../components/ValidateButton'; +import AsyncStorage from '@react-native-async-storage/async-storage'; +import EventEmitter from './EventEmitter'; + +import plus from '../assets/images/plus.png'; +import moins from '../assets/images/minus.png'; export default function IngredientSelection(props) { + const colors = useContext(ColorContext).colors + 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 ingredientService = new IngredientService(); - const {colors} = useContext(ColorContext); const [availableSize, setAvailableSize] = useState(0); const [listVisibility, setListVisibility] = useState("flex"); const [availableVisibility, setAvailableVisibility] = useState("none"); @@ -57,6 +62,8 @@ const loadIngredients = async () => { useEffect(() => { loadIngredients(); + fetchAvailableIngredient(); + ChangeAvailableSize(true) }, []); const AvailableItem = ({ value }: { value: Ingredient }) => ( @@ -87,20 +94,70 @@ const loadIngredients = async () => { ); - const SelectIngredient = (newIngredient: Ingredient) => { - const exists = selectedIngredients.find((ingredient) => ingredient.id === newIngredient.id); - if (!exists) { - setSelectedIngredients([...selectedIngredients, newIngredient]); - ChangeAvailableSize(false) + const handleGetAvailableIngredient = async () => { + try { + const existingAvailableIngredient = await AsyncStorage.getItem('ingredient'); + return JSON.parse(existingAvailableIngredient) || []; + } catch (error) { + console.log(error); + return []; + } +} + +const fetchAvailableIngredient = async () => { + const existingAvailableIngredient = await handleGetAvailableIngredient(); + if (existingAvailableIngredient.length != 0){ + setSelectedIngredients(existingAvailableIngredient); + } + else{ + setSelectedIngredients([{value: "None"}]) + } +}; + + const SelectIngredient = async (newIngredient: Ingredient) => { + try{ + const exists = selectedIngredients.find((ingredient) => ingredient.id === newIngredient.id); + if (!exists) { + let existingAvailableIngredient = await AsyncStorage.getItem('ingredient'); + existingAvailableIngredient = existingAvailableIngredient ? JSON.parse(existingAvailableIngredient) : []; + const updatedAvailableIngredient = [...existingAvailableIngredient, newIngredient]; + await AsyncStorage.setItem('ingredient', JSON.stringify(updatedAvailableIngredient)); + EventEmitter.emit('ingredientAdded'); + console.log('Ingredient Added:', newIngredient); + ChangeAvailableSize(false) + } + } + catch(error){ + console.log("Error occured during the addition of Ingredient:", error) } }; - const RemoveIngredient = (idIngredient: number) => { - const updatedIngredients = selectedIngredients.filter((ingredient) => ingredient.id !== idIngredient); - setSelectedIngredients(updatedIngredients); - ChangeAvailableSize(true) + const RemoveIngredient = async (idIngredient: number) => { + try{ + const updatedIngredients = selectedIngredients.filter((ingredient) => ingredient.id !== idIngredient); + await AsyncStorage.setItem('ingredient', JSON.stringify(updatedIngredients)); + EventEmitter.emit('ingredientDeleted'); + fetchAvailableIngredient(); + setSelectedIngredients(updatedIngredients); + ChangeAvailableSize(true) + } + catch (error){ + console.log("Error occured during the suppression of Ingredient:", error) + } }; + const subscriptionAddIngredient = EventEmitter.addListener('ingredientAdded', async () => { + fetchAvailableIngredient(); + }); + const subscriptionDeleteIngredient = EventEmitter.addListener('ingredientDeleted', async () => { + if (selectedIngredients.length == 1){ + setSelectedIngredients([{title: "None"}]) + } + else{ + fetchAvailableIngredient(); + } + }); + const ChangeAvailableSize = (remove: boolean) => { if(remove){ if (selectedIngredients.length == 1){ @@ -124,7 +181,12 @@ const loadIngredients = async () => { setAvailableSize(90) } else if (selectedIngredients.length == 1){ - setAvailableSize(180) + if(selectedIngredients[0].value == "None"){ + setAvailableSize(90) + } + else{ + setAvailableSize(180) + } } else if (selectedIngredients.length == 2){ setAvailableSize(260) diff --git a/LeftOvers/screens/Profiles.tsx b/LeftOvers/screens/Profiles.tsx index 1f6803a..e763b8f 100644 --- a/LeftOvers/screens/Profiles.tsx +++ b/LeftOvers/screens/Profiles.tsx @@ -5,21 +5,15 @@ import { LinearGradient } from 'expo-linear-gradient'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import ProfileDetails from '../components/ProfileDetails'; -import ProfileDelete from '../components/ProfileDelete'; 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}) { - const { colors, toggleColors } = useContext(ColorContext) - - const all = [] - const die = [{value: "Dairy free"}, {value: "Gluten free"}, {value: "Porkless"}, {value: "Vegan"}, {value: "Vegetarian"}, {value: "Pescatarian"}] - + const colors = useContext(ColorContext).colors + const [visible, setVisible] = useState(false); - const [opacity, setOpacity] = useState(1); const [profiles, setProfiles] = useState([]); const [selectedProfileIndex, setSelectedProfileIndex] = useState(null); @@ -34,19 +28,11 @@ export default function Profiles({navigation, props}) { setVisible(false) } - const handleDeleteProfiles = async () => { - try { - await AsyncStorage.removeItem('profiles'); - console.log('Données supprimées avec succès !'); - } catch (error) { - console.error('Erreur lors de la suppression des données :', error); - } - }; - const handleDeleteProfile = async (index) => { try { const updatedProfiles = profiles.filter((profile, i) => i !== index); await AsyncStorage.setItem('profiles', JSON.stringify(updatedProfiles)); + EventEmitter.emit('profileDeleted'); fetchProfiles(); setSelectedProfileIndex(index); erasePopUp(); @@ -55,16 +41,12 @@ export default function Profiles({navigation, props}) { } }; - const confirmDelete = () => { - erasePopUp(); - }; - - const handleGetProfiles = async () => { + const handleGetProfiles = async () => { try { const existingProfiles = await AsyncStorage.getItem('profiles'); return JSON.parse(existingProfiles) || []; } catch (error) { - console.log("ça maaaaaaaaarche poaaaaaaaaaaaas"); + console.log("Error occured during GetProfiles", error); return []; } } @@ -80,16 +62,13 @@ export default function Profiles({navigation, props}) { useEffect(() => { fetchProfiles(); - console.log(profiles) }, []); const containerStyle = { height: "75%", width: "100%", - }; - - - const styles = StyleSheet.create({ + }; + const styles = StyleSheet.create({ container: { height: "100%", width: "100%", @@ -201,7 +180,7 @@ export default function Profiles({navigation, props}) { const profileComponents = profiles.map((profile, index) => ( - - {index < profiles.length - 1 && } + {index < profiles.length - 1 && } )); - - return ( diff --git a/LeftOvers/screens/RecipeDetails.tsx b/LeftOvers/screens/RecipeDetails.tsx index fe56366..39282e5 100644 --- a/LeftOvers/screens/RecipeDetails.tsx +++ b/LeftOvers/screens/RecipeDetails.tsx @@ -28,7 +28,6 @@ export default function RecipeDetails({ route }) { const recipe = await recipesService.getRecipeById(recipeId); console.log("Recipe.name: "+recipe.name) setResponse(recipe); - console.log("Response.name: "+response.name) } catch (error) { console.log(error); } finally{ @@ -37,7 +36,6 @@ export default function RecipeDetails({ route }) { }; useEffect(() => { - console.log("Je passe ici (useEffect)") loadRecipe(); }, []);