diff --git a/src/App.js b/src/App.js index cc7300db0..d40c3055d 100644 --- a/src/App.js +++ b/src/App.js @@ -14,6 +14,7 @@ import { NotFoundPage, NutriscoreValidator, Home, + Nutrition, } from "./pages"; import ResponsiveAppBar from "./components/ResponsiveAppBar"; import DevModeContext from "./contexts/devMode"; @@ -126,6 +127,7 @@ export default function App() { } /> } /> } /> + } /> } /> } /> diff --git a/src/i18n/common.json b/src/i18n/common.json index b0a4ff57a..ffa475a2d 100644 --- a/src/i18n/common.json +++ b/src/i18n/common.json @@ -190,7 +190,32 @@ "nutriment_proteins": "Proteins", "nutriment_fiber": "Fibers", "nutriment_salt": "Salt", - "nutriment_sodium": "Sodium" + "nutriment_sodium": "Sodium", + "nutriment_zinc" : "Zinc", + "nutriment_vitamin-c" : "Vitamin-c", + "nutriment_vitamin-d" : "Vitamin-d", + "nutriment_vitamin-k" : "Vitamin-k", + "nutriment_vitamin-b6" : "Vitamin-b6", + "nutriment_vitamin-a" : "Vitamin-a", + "nutriment_selenium" : "Selenium", + "nutriment_bicarbonate" : "Bicarbonate", + "nutriment_magnesium" : "Magnesium", + "nutriment_pantothenic-acid" : "Pantothenic-acid", + "nutriment_fluoride" : "Fluoride", + "nutriment_iodine" : "Iodine", + "nutriment_silica" : "Silica", + "nutriment_alcohol" : "Alcohol", + "nutriment_potassium" : "Potassium", + "nutriment_manganese" : "Manganese", + "nutriment_phosphorus" : "Phosphorus", + "nutriment_biotin" : "Biotin", + "nutriment_ph" : "Ph", + "nutriment_molybdenum" : "Molybdenum", + "nutriment_caffeine" : "Caffeine", + "nutriment_chromium" : "Chromium", + "nutriment_iron" : "Iron", + "nutriment_copper" : "Copper", + "nutriment_cholesterol": "Cholesterol" }, "history": { "title": "Session History", diff --git a/src/i18n/en.json b/src/i18n/en.json index 8cff1b867..147169f57 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -190,7 +190,32 @@ "nutriment_proteins": "Protein content", "nutriment_fiber": "Fibers", "nutriment_salt": "Salt", - "nutriment_sodium": "Sodium" + "nutriment_sodium": "Sodium", + "nutriment_zinc" : "Zinc", + "nutriment_vitamin-c" : "Vitamin-c", + "nutriment_vitamin-d" : "Vitamin-d", + "nutriment_vitamin-k" : "Vitamin-k", + "nutriment_vitamin-b6" : "Vitamin-b6", + "nutriment_vitamin-a" : "Vitamin-a", + "nutriment_selenium" : "Selenium", + "nutriment_bicarbonate" : "Bicarbonate", + "nutriment_magnesium" : "Magnesium", + "nutriment_pantothenic-acid" : "Pantothenic-acid", + "nutriment_fluoride" : "Fluoride", + "nutriment_iodine" : "Iodine", + "nutriment_silica" : "Silica", + "nutriment_alcohol" : "Alcohol", + "nutriment_potassium" : "Potassium", + "nutriment_manganese" : "Manganese", + "nutriment_phosphorus" : "Phosphorus", + "nutriment_biotin" : "Biotin", + "nutriment_ph" : "Ph", + "nutriment_molybdenum" : "Molybdenum", + "nutriment_caffeine" : "Caffeine", + "nutriment_chromium" : "Chromium", + "nutriment_iron" : "Iron", + "nutriment_copper" : "Copper", + "nutriment_cholesterol": "Cholesterol" }, "history": { "title": "Session History", diff --git a/src/pages/index.js b/src/pages/index.js index c534ee76d..3ec479b53 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -11,3 +11,4 @@ export { default as LogoUpdatePage } from "./logos/LogoUpdate"; // experimental export { default as NutriscoreValidator } from "./nutriscoreValidator"; +export { default as Nutrition } from "./nutrition" diff --git a/src/pages/nutrition/additionalNutritions.jsx b/src/pages/nutrition/additionalNutritions.jsx new file mode 100644 index 000000000..33af96a34 --- /dev/null +++ b/src/pages/nutrition/additionalNutritions.jsx @@ -0,0 +1,35 @@ +import * as React from "react"; +import TextField from "@mui/material/TextField"; +import Autocomplete from "@mui/material/Autocomplete"; +import { useTranslation } from "react-i18next"; + +export default function AdditionalNutriments({ options, setNutriments }) { + const [inputValue, setInputValue] = React.useState(""); + const { t } = useTranslation(); + + return ( + { + const nutr = event.target.innerText; + const nutrName = options.find((item) => item.label === nutr).id; + + setNutriments((prev) => + prev.map((nutr) => + nutr.label === nutrName ? { ...nutr, display: true } : nutr + ) + ); + setInputValue(""); + }} + inputValue={inputValue} + onInputChange={(event, newInputValue) => { + setInputValue(newInputValue); + }} + renderInput={(params) => } + /> + ); +} diff --git a/src/pages/nutrition/index.jsx b/src/pages/nutrition/index.jsx new file mode 100644 index 000000000..6c2bbbe8c --- /dev/null +++ b/src/pages/nutrition/index.jsx @@ -0,0 +1,57 @@ +import * as React from "react"; +import NutritionTable from "./table"; +import ProductNutriments from "./productCard"; +import { Box } from "@mui/material"; + +import { basicNutriments } from "./nutritionFields"; + +export default function Nutrition() { + const [nutriments, setNutriments] = React.useState(basicNutriments); + + function onchangeHandler(e) { + const { value, name, id } = e.target; + console.log(name); + setNutriments((prevState) => + prevState.map((nutr) => { + return id === nutr.label ? { ...nutr, [name]: value } : nutr; + }) + ); + } + + function deleteItem(nutr) { + setNutriments((prev) => + prev.map((nutriment) => + nutriment === nutr ? { ...nutriment, display: false } : nutriment + ) + ); + } + + return ( + + + nutr.display)} + setNutriments={setNutriments} + additionalNutriments={nutriments.filter((nutr) => !nutr.display)} + onchangeHandler={onchangeHandler} + deleteItem={deleteItem} + /> + + ); +} diff --git a/src/pages/nutrition/nutritionFields.js b/src/pages/nutrition/nutritionFields.js new file mode 100644 index 000000000..4f1535daa --- /dev/null +++ b/src/pages/nutrition/nutritionFields.js @@ -0,0 +1,342 @@ +const basicNutriments = [ + { + off_nutriment_id: "energy-kj", + label: "nutriment_energy-kj", + value: "", + unit: null, + quantification: "=", + robotoffPrediction: null, + display: true, + }, + { + off_nutriment_id: "energy-kcal", + label: "nutriment_energy-kcal", + value: "", + unit: null, + quantification: "<", + robotoffPrediction: null, + display: true, + }, + { + off_nutriment_id: "nutriment_fat", + label: "nutriment_fat", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: true, + }, + { + off_nutriment_id: "saturated-fat", + label: "nutriment_saturated-fat", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: true, + }, + { + off_nutriment_id: "carbohydrates", + label: "nutriment_carbohydrates", + value: "", + unit: "g", + quantification: "=", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "sugars", + label: "nutriment_sugars", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "proteins", + label: "nutriment_proteins", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "fiber", + label: "nutriment_fiber", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "salt", + label: "nutriment_salt", + value: "", + unit: "g", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "sodium", + label: "nutriment_sodium", + value: "", + unit: null, + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "zinc", + label: "nutriment_zinc", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "vitamin-c", + label: "nutriment_vitamin-c", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "vitamin-d", + label: "nutriment_vitamin-d", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "vitamin-k", + label: "nutriment_vitamin-k", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "vitamin-b6", + label: "nutriment_vitamin-b6", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "vitamin-a", + label: "nutriment_vitamin-a", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "selenium", + label: "nutriment_selenium", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "bicarbonate", + label: "nutriment_bicarbonate", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "magnesium", + label: "nutriment_magnesium", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "pantothenic-acid", + label: "nutriment_pantothenic-acid", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "fluoride", + label: "nutriment_fluoride", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "iodine", + label: "nutriment_iodine", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "silica", + label: "nutriment_silica", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "alcohol", + label: "nutriment_alcohol", + value: "", + unit: "% vol", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "potassium", + label: "nutriment_potassium", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "manganese", + label: "nutriment_manganese", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "phosphorus", + label: "nutriment_phosphorus", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "biotin", + label: "nutriment_biotin", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + { + off_nutriment_id: "ph", + label: "nutriment_ph", + value: "", + unit: null, + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "molybdenum", + label: "nutriment_molybdenum", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "caffeine", + label: "nutriment_caffeine", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "chromium", + label: "nutriment_chromium", + value: "", + unit: "µg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "iron", + label: "nutriment_iron", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "copper", + label: "nutriment_copper", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, + + { + off_nutriment_id: "cholesterol", + label: "nutriment_cholesterol", + value: "", + unit: "mg", + quantification: "<", + robotoffPrediction: null, + display: false, + }, +]; + +export { basicNutriments }; diff --git a/src/pages/nutrition/productCard.jsx b/src/pages/nutrition/productCard.jsx new file mode 100644 index 000000000..1fa1f68b5 --- /dev/null +++ b/src/pages/nutrition/productCard.jsx @@ -0,0 +1,108 @@ +import * as React from "react"; +import Box from "@mui/material/Box"; +import Zoom from "react-medium-image-zoom"; +import Button from "@mui/material/Button"; +import Typography from "@mui/material/Typography"; +import offService from "../../off"; + +import { basicNutriments } from "./nutritionFields"; + +export default function ProductNutriments({ setNutriments, nutriments }) { + const [page, setPage] = React.useState(1); + const [index, setIndex] = React.useState(0); + const [products, setProducts] = React.useState([]); + + const product = products[index]; + const productName = product + ? product.product_name + ? product.product_name + : "Brand Unknown" + : "Loading..."; + + React.useEffect(() => { + const productListUrl = offService.getNutritionToFillUrl({ page }); + + fetch(productListUrl) + .then((res) => res.json()) + .then((data) => { + setProducts(data.products); + }); + }, [page]); + + const pictureURL = products[index] + ? products[index].image_nutrition_url + : "https://static.openfoodfacts.org/images/image-placeholder.png"; + + function clickHandler() { + setIndex((prev) => (prev < 22 ? ++prev : 0)); + console.log(nutriments.filter((nutr) => nutr.display && nutr.value)); + setNutriments(basicNutriments); + } + + return ( + + + + + + + {productName} + + {/**/} + {/* PRODUCT DESCRIPTION IF NEEDED*/} + {/**/} + + + + + ); +} diff --git a/src/pages/nutrition/table.jsx b/src/pages/nutrition/table.jsx new file mode 100644 index 000000000..ee9cad111 --- /dev/null +++ b/src/pages/nutrition/table.jsx @@ -0,0 +1,77 @@ +import * as React from "react"; +import Table from "@mui/material/Table"; +import TableBody from "@mui/material/TableBody"; +import TableCell from "@mui/material/TableCell"; +import TableContainer from "@mui/material/TableContainer"; +import TableHead from "@mui/material/TableHead"; +import TableRow from "@mui/material/TableRow"; +import { Box } from "@mui/material"; +import AdditionalNutriments from "./additionalNutritions"; +import { useTranslation } from "react-i18next"; + +import TableRowComp from "./tableRow"; + +export default function NutritionTable({ + nutriments, + setNutriments, + additionalNutriments, + deleteItem, + onchangeHandler, +}) { + const { t } = useTranslation(); + + const rows = nutriments.map((nutriment) => ( + + )); + const options = additionalNutriments.map((item) => ({ + label: t(`nutrition.nutriments.${item.label}`), + id: item.label, + })); + + return ( + + + + + + + + {t("nutrition.table.value")} + + + + + + {rows} +
+
+
+ ); +} diff --git a/src/pages/nutrition/tableRow.jsx b/src/pages/nutrition/tableRow.jsx new file mode 100644 index 000000000..f3aebf233 --- /dev/null +++ b/src/pages/nutrition/tableRow.jsx @@ -0,0 +1,84 @@ +import * as React from "react"; +import TableCell from "@mui/material/TableCell"; +import TableRow from "@mui/material/TableRow"; +import TextField from "@mui/material/TextField"; +import SelectUnit from "./unitSelect"; +import { Typography } from "@mui/material"; +import { Box } from "@mui/material"; +import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; + +import { useTranslation } from "react-i18next"; + +function createData(label, property, deleteIcon) { + return { label, property, deleteIcon }; +} + +export default function TableRowComp({ + nutriment, + onchangeHandler, + deleteItem, +}) { + const { t } = useTranslation(); + + const row = createData( + + {t(`nutrition.nutriments.${nutriment.label}`)} + + + + + + + , + deleteItem(nutriment)} + /> + ); + + return ( + + + {row.label} + + + {row.property} + + + ); +} diff --git a/src/pages/nutrition/unitSelect.jsx b/src/pages/nutrition/unitSelect.jsx new file mode 100644 index 000000000..12ee67e42 --- /dev/null +++ b/src/pages/nutrition/unitSelect.jsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import InputLabel from "@mui/material/InputLabel"; +import MenuItem from "@mui/material/MenuItem"; +import FormControl from "@mui/material/FormControl"; +import Select, { SelectChangeEvent } from "@mui/material/Select"; + +export default function SelectUnit({ options, value, onchangeHandler }) { + return ( +
+ + {options && ( + + )} + +
+ ); +}