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": {
"@expo/webpack-config": "^19.0.0",
"@types/react": "~18.2.14",
"axios": "^1.6.2",
"expo": "~49.0.15",
"expo-linear-gradient": "~12.3.0",
"expo-splash-screen": "~0.20.5",
@ -6735,6 +6736,29 @@
"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": {
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
@ -14620,6 +14644,11 @@
"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": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",

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

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

Loading…
Cancel
Save