Optimisation of displaying ingredients, and add filters
continuous-integration/drone/push Build is failing Details

pull/20/head
Rayhân HASSOU 1 year ago
parent 1b1cf41a19
commit a29c5b78ec

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

@ -0,0 +1,33 @@
import Ingredient from "../../Models/Ingredient";
import IIngredientService from "./IIngredientService";
import axios from 'axios';
export default class IngredientService implements IIngredientService {
private readonly API_URL = "http://localhost:3000/ingredients";
constructor() {}
async getAllIngredient(): Promise<Ingredient[]> {
try {
const response = await axios.get(this.API_URL);
return response.data as Ingredient[];
} catch (error) {
throw new Error('Erreur lors de la récupération des ingrédients : ' + error.message);
}
}
async getIngredientById(id: Number): Promise<Ingredient | null>{
return;
}
async getIngredientByLetter(letter: String): Promise<any>{
try {
const response = await axios.get(`${this.API_URL}/letter/${letter}`);
return response.data as Ingredient[];
} catch (error) {
throw new Error('Erreur lors de la récupération des ingrédients : ' + error.message);
}
}
}

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"@expo/webpack-config": "^19.0.0", "@expo/webpack-config": "^19.0.0",
"@types/react": "~18.2.14", "@types/react": "~18.2.14",
"axios": "^1.6.2",
"expo": "~49.0.15", "expo": "~49.0.15",
"expo-linear-gradient": "~12.3.0", "expo-linear-gradient": "~12.3.0",
"expo-splash-screen": "~0.20.5", "expo-splash-screen": "~0.20.5",
@ -6735,6 +6736,29 @@
"node": ">= 4.0.0" "node": ">= 4.0.0"
} }
}, },
"node_modules/axios": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz",
"integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-core": { "node_modules/babel-core": {
"version": "7.0.0-bridge.0", "version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
@ -14620,6 +14644,11 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pump": { "node_modules/pump": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",

@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"@expo/webpack-config": "^19.0.0", "@expo/webpack-config": "^19.0.0",
"@types/react": "~18.2.14", "@types/react": "~18.2.14",
"axios": "^1.6.2",
"expo": "~49.0.15", "expo": "~49.0.15",
"expo-linear-gradient": "~12.3.0", "expo-linear-gradient": "~12.3.0",
"expo-splash-screen": "~0.20.5", "expo-splash-screen": "~0.20.5",

@ -1,72 +1,39 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import {View, StyleSheet, Text, Image, Pressable, ScrollView, ActivityIndicator} from 'react-native'; import { View, StyleSheet, Text, Image, Pressable, ActivityIndicator, FlatList } from 'react-native';
import {SafeAreaProvider} from 'react-native-safe-area-context'; import { SafeAreaProvider } from 'react-native-safe-area-context';
import TopBar from '../components/TopBar'; import TopBar from '../components/TopBar';
import {Searchbar} from 'react-native-paper'; import { Searchbar } from 'react-native-paper';
import FoodElementText from '../components/FoodElementText'; import FoodElementText from '../components/FoodElementText';
import CustomButton from '../components/CustomButton'; import CustomButton from '../components/CustomButton';
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';
import meat from '../assets/images/meat_icon.png'; import Ingredient from '../Models/Ingredient';
import vegetable from '../assets/images/vegetable_icon.png'; import IngredientService from '../Services/Ingredients/IngredientsServices';
import fruit from '../assets/images/fruit_icon.png';
import Ingredient from '../Models/Ingredient'
export default function IngredientSelection(props) { export default function IngredientSelection(props) {
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
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"];
let [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
let [error, setError] = useState(); const [error, setError] = useState();
let [response, setResponse] = useState(); const [response, setResponse] = useState<Ingredient[] | undefined>(undefined);
let [SelectedIngredient, setSelectedIngredients] = useState([]); const [selectedIngredients, setSelectedIngredients] = useState([]);
let instancesArray: Array<any> = []; const ingredientService = new IngredientService();
const loadIngredients = async () => {
// Pour se connecter à l'API try {
useEffect(() => { const ingredients = await ingredientService.getAllIngredient();
fetch('http://localhost:3000/ingredients') setResponse(ingredients);
.then(res => res.json()) } catch (error) {
.then( setError(error);
result => { } finally {
setIsLoading(false); setIsLoading(false);
setResponse(result);
},
error => {
setIsLoading(false);
setError(error);
}
);
}, []);
// Pour
const getContent = () => {
if (isLoading) {
return <ActivityIndicator size="large" />;
}
if (error) {
console.log('Erreur ici' + error);
return <Text>Ca marche Pos</Text>;
}
if (response) {
try {
instancesArray = Ingredient.convertApiResponse(JSON.stringify(response));
return instancesArray.map((ingredient, index) => (
<AvailableItem key={index} value={ingredient} />
));
} catch (error) {
console.error("Erreur de conversion de la réponse en instances d'Ingredient:", error);
return <Text>Erreur lors du traitement des données</Text>;
}
} }
}; };
// Ingredients disponible useEffect(() => {
loadIngredients();
}, []);
const AvailableItem = ({ value }: { value: Ingredient }) => ( const AvailableItem = ({ value }: { value: Ingredient }) => (
<> <>
<View style={styles.horizontalAlignement}> <View style={styles.horizontalAlignement}>
@ -79,8 +46,7 @@ export default function IngredientSelection(props) {
</> </>
); );
// Ingredient choisi par l'utilisateur const ChooseItem = ({ value }: { value: Ingredient }) => (
const ChooseItem = ({ value }: { value: { id: number; name: string } }) => (
<> <>
<View style={styles.horizontalAlignement}> <View style={styles.horizontalAlignement}>
<FoodElementText title={value.name} /> <FoodElementText title={value.name} />
@ -92,90 +58,98 @@ export default function IngredientSelection(props) {
</> </>
); );
function SelectIngredient(newIngredient: Ingredient) { const SelectIngredient = (newIngredient: Ingredient) => {
const exists = SelectedIngredient.find( const exists = selectedIngredients.find((ingredient) => ingredient.id === newIngredient.id);
(ingredient) => ingredient.id === newIngredient.id
);
if (!exists) { if (!exists) {
setSelectedIngredients([...SelectedIngredient, newIngredient]); setSelectedIngredients([...selectedIngredients, newIngredient]);
console.log(newIngredient);
console.log(SelectedIngredient);
}else{
console.log(exists)
console.log("cheh pas ajouté")
} }
} };
function RemoveIngredient(idIngredient: Number){
const updatedIngredients = SelectedIngredient.filter(
(ingredient) => ingredient.id !== idIngredient
);
setSelectedIngredients(updatedIngredients); const RemoveIngredient = (idIngredient: number) => {
} const updatedIngredients = selectedIngredients.filter((ingredient) => ingredient.id !== idIngredient);
setSelectedIngredients(updatedIngredients);
};
const handleLetterPress = async (letter: string) => {
try {
const ingredientsByLetter = await ingredientService.getIngredientByLetter(letter);
setResponse(ingredientsByLetter);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
};
return ( return (
<SafeAreaProvider> <SafeAreaProvider>
<TopBar title="Ingredient selection" /> <TopBar title="Ingredient selection" />
<ScrollView contentContainerStyle={{ alignItems: 'center', height: '100%'}}> <View style={styles.page}>
<View style={styles.page}> <View style={styles.element}>
<View style={styles.element}>
<View style={[styles.horizontalAlignement, {justifyContent: 'center'}]}> <View style={[styles.horizontalAlignement, { margin: 10 }]}>
<Pressable> {alphabetArray.map((source, index) => (
<Image source={meat} style={{ width: 30, height: 30 }} /> <Pressable key={index} onPress={() => handleLetterPress(source)}>
</Pressable> <Text style={{ color: "blue" }}>{source}</Text>
<Pressable> </Pressable>
<Image source={vegetable} style={{ width: 30, height: 30 }} /> ))}
</Pressable> </View>
<Pressable>
<Image source={fruit} style={{ width: 30, height: 30 }} /> <View>
</Pressable> <Searchbar
</View> placeholder="Rechercher"
<View> onChangeText={query => setSearchValue(query)}
<Searchbar value={searchValue}
placeholder="Rechercher" style={{
onChangeText={query => setSearchValue(query)} margin: 10,
value={searchValue} backgroundColor: '#F2F0E4',
style={{margin: 10, borderWidth: 1,
backgroundColor: '#F2F0E4', borderColor: "#ACA279",
borderWidth : 1, borderRadius: 15,
borderColor: "#ACA279", height: 50,
borderRadius: 15, }} />
height: 50, </View>
}}/>
<View style={{ alignItems: 'center', height: 300}}>
</View> <FlatList
<View style={{ flex: 1}} > data={response ? response : []}
<ScrollView contentContainerStyle={{ alignItems: 'center', height: 300}}> renderItem={({ item }) => (
{getContent()} <AvailableItem value={item} />
</ScrollView> )}
</View> keyExtractor={(item, index) => index.toString()}
<View style={{ height: 20 }}></View> ListEmptyComponent={() => (
</View> isLoading ? <ActivityIndicator size="large" /> : <Text>Erreur lors du traitement des données</Text>
)}
<View style={[styles.element, {marginTop: 40}]}> style={{ flex: 1 }}
<View style={[styles.horizontalAlignement, {justifyContent: "flex-start", marginLeft: 10}]}> />
<Text style={{fontSize: 20, color: '#ACA279'}}>Available</Text> </View>
</View> <View style={{ height: 20 }}></View>
</View>
<View style={{ height: 5 }}></View>
<View style={[styles.element, { marginTop: 40 }]}>
<View style={{ flex: 1}} > <View style={[styles.horizontalAlignement, { justifyContent: "flex-start", marginLeft: 10 }]}>
<ScrollView contentContainerStyle={{ alignItems: 'center', height: 150}}> <Text style={{ fontSize: 20, color: '#ACA279' }}>Selected</Text>
{SelectedIngredient.map((source, index) => ( </View>
<ChooseItem key={index} value={source}></ChooseItem> <View style={{ height: 5 }}></View>
))}
</ScrollView> <View style={{ alignItems: 'center', maxHeight: 200}}>
</View> <FlatList
<View style={{ height: 20 }}></View> data={selectedIngredients}
</View> renderItem={({ item }) => (
<ChooseItem value={item} />
<View style={{ height: 15 }}></View> )}
<CustomButton title="Find a recipe"/> keyExtractor={(item, index) => index.toString()}
</View> style={{ flex: 1 }}
</ScrollView> />
</View>
<View style={{ height: 20 }}></View>
</View>
<View style={{ height: 15 }}></View>
<CustomButton title="Find a recipe" />
</View>
</SafeAreaProvider> </SafeAreaProvider>
); );
} }
@ -190,7 +164,7 @@ const styles = StyleSheet.create({
padding: 20, padding: 20,
}, },
element: { element: {
backgroundColor:'#F2F0E4', backgroundColor: '#F2F0E4',
borderRadius: 30, borderRadius: 30,
}, },
horizontalAlignement: { horizontalAlignement: {

Loading…
Cancel
Save