Skip to content

Commit

Permalink
nutrient prediction added to tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
tahmid-saj committed Jun 17, 2024
1 parent 7333b1f commit 3d5a951
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/components/shared/button/button.styles.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@ export const RoundedButton = styled(BaseButton)`

export const ButtonsContainer = styled.div`
display: flex;
justify-content: space-between;
justify-content: space-evenly;
align-items: center;
`
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,119 @@ import { NutrientPredictorContext } from "../../../../contexts/shared/nutrient-p
import { Divider, Typography } from "@mui/material";
import OutlinedCard from "../../mui/card/card.component.jsx";
import { COLOR_CODES } from "../../../../utils/constants/shared.constants.js";
import Button from "../../button/button.component.jsx";
import { ButtonsContainer } from "../../button/button.styles.jsx";
import { useDispatch, useSelector } from "react-redux";
import { selectCurrentUser } from "../../../../store/shared/user/user.selector.js"
import { NutritionTrackerContext } from "../../../../contexts/signed-in/nutrition-tracker/nutrition-tracker.context.js";
import { addDayTrackedFromPrediction, setFormInputMicronutrients } from "../../../../store/signed-out/nutrition-tracker/nutrition-tracker.action.js";
import { selectNutritionTrackedDays } from "../../../../store/signed-out/nutrition-tracker/nutrition-tracker.selector.js";

const outlinedCardStyles = {
backgroundColor: COLOR_CODES.card.infoCard
}

const NutrientsInfo = () => {
const { nutrientPredictions } = useContext(NutrientPredictorContext);
const currentUser = useSelector(selectCurrentUser)

console.log(nutrientPredictions)
const { addDayTrackedFromPrediction: addDayTrackedFromPredictionSignedIn } = useContext(NutritionTrackerContext)

const dispatch = useDispatch()
const nutritionTrackedDays = useSelector(selectNutritionTrackedDays)


const handleAddToTracker = (prediction) => {
const currentDate = new Date()
const predictionNutritionInfo = {
dateTracked: currentDate.toISOString().split('T')[0],
calories: Number(prediction.calories),
macronutrients: {
carbohydrates: Number(prediction.macronutrients.carbohydratesTotalG),
protein: Number(prediction.macronutrients.proteinG),
fat: Number(prediction.macronutrients.fatTotalG)
},
micronutrients: [
{
name: "Sodium",
amount: Number(prediction.micronutrients.sodiumMG),
unit: "mg"
},
{
name: "Potassium",
amount: Number(prediction.micronutrients.potassiumMG),
unit: "mg"
},
{
name: "Cholesterol",
amount: Number(prediction.micronutrients.cholesterolMg),
unit: "mg"
},
{
name: "Fiber",
amount: Number(prediction.micronutrients.fiberG),
unit: "g"
},
{
name: "Sugar",
amount: Number(prediction.micronutrients.sugarG),
unit: "g"
},
]
}

// signed in
if (currentUser) {
addDayTrackedFromPredictionSignedIn(predictionNutritionInfo)

// signed out
} else {
dispatch(addDayTrackedFromPrediction(nutritionTrackedDays, predictionNutritionInfo))
dispatch(setFormInputMicronutrients([]))
}
}

return (
nutrientPredictions.map((prediction, index) => {
return (
<NutrientsInfoContainer key={ index }>
<OutlinedCard styles={ outlinedCardStyles }>
<strong><Typography sx={{ display: "flex", justifyContent: "center" }} variant="h6">{`${prediction.name.toUpperCase()}`}</Typography></strong>
<br></br>
<strong><Typography sx={{ display: "flex", justifyContent: "center" }} variant="h6">{`${prediction.name.toUpperCase()}`}</Typography></strong>
<br></br>

<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Calories - ${prediction.calories}`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Serving size - ${prediction.servingSizeG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Calories - ${prediction.calories}`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Serving size - ${prediction.servingSizeG} g`}</Typography>

<br></br>
<Divider/>
<br></br>
<br></br>
<Divider/>
<br></br>

<strong><h4>Macronutrients</h4></strong>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Carbohydrates - ${prediction.macronutrients.carbohydratesTotalG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Protein - ${prediction.macronutrients.proteinG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Fat - ${prediction.macronutrients.fatTotalG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Saturated fat - ${prediction.macronutrients.fatSaturatedG} g`}</Typography>
<strong><h4>Macronutrients</h4></strong>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Carbohydrates - ${prediction.macronutrients.carbohydratesTotalG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Protein - ${prediction.macronutrients.proteinG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Fat - ${prediction.macronutrients.fatTotalG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Saturated fat - ${prediction.macronutrients.fatSaturatedG} g`}</Typography>

<br></br>
<Divider/>
<br></br>
<br></br>
<Divider/>
<br></br>

<strong><h4>Micronutrients</h4></strong>
<strong><h4>Micronutrients</h4></strong>
<Fragment key={ index }>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Sodium - ${prediction.micronutrients.sodiumMG} mg`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Potassium - ${prediction.micronutrients.potassiumMG} mg`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Cholesterol - ${prediction.micronutrients.cholesterolMg} mg`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Fiber - ${prediction.micronutrients.fiberG} g`}</Typography>
<Typography sx={{ display: "flex", justifyContent: "center" }} variant="body1">{`Sugar - ${prediction.micronutrients.sugarG} g`}</Typography>
</Fragment>

<br></br>
<Divider/>
<br></br>

<ButtonsContainer>
<Button buttonType="regular-button" type="button" onClick={ () => handleAddToTracker(prediction) }>Add to tracker</Button>
</ButtonsContainer>
</OutlinedCard>
</NutrientsInfoContainer>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, useState, useEffect, useContext } from "react";

import { validateAddDayTracked, validateUpdateDayTracked,
import { validatePredictionInfo, validateAddDayTracked, validateUpdateDayTracked,
validateFilterNutritionTrackedDays, validateRemoveNutritionTrackedDay } from "../../../utils/validations/nutrition-tracker.validations";
import { calculateSummary } from "../../../utils/calculations/nutrition-tracker.calculations";

Expand All @@ -17,6 +17,24 @@ import { getNutritionTrackedDaysData, getNutritionTrackedDaysSummaryData,
// TODO: sort the records by date
// helper functions

const addDayTrackedFromPredictionHelper = (nutritionTrackedDays, predictionNutritionInfo) => {
if (validatePredictionInfo(nutritionTrackedDays, predictionNutritionInfo)) return nutritionTrackedDays

return [
...nutritionTrackedDays,
{
dateTracked: String(predictionNutritionInfo.dateTracked),
calories: Number(predictionNutritionInfo.calories),
macronutrients: {
carbohydrates: Number(predictionNutritionInfo.macronutrients.carbohydrates),
protein: Number(predictionNutritionInfo.macronutrients.protein),
fat: Number(predictionNutritionInfo.macronutrients.fat),
},
micronutrients: predictionNutritionInfo.micronutrients
}
]
}

const addMicronutrientsToTrackedDayInfoHelper = (formInputMicronutrients, trackedDayInfo) => {
return {
...trackedDayInfo,
Expand Down Expand Up @@ -215,6 +233,8 @@ export const NutritionTrackerContext = createContext({
updateFormInputMicronutrients: () => {},
deleteFormInputMicronutrients: () => {},

addDayTrackedFromPrediction: () => {},

nutritionTrackedDaysSummary: {},
// nutritionTrackedDaysSummary structure:
// {
Expand Down Expand Up @@ -360,13 +380,19 @@ export const NutritionTrackerProvider = ({ children }) => {
putNutritionTrackedDaysSummary(currentUser.uid, currentUser.email, nutritionTrackedDaysSummary);
};

const addDayTrackedFromPrediction = (predictionNutritionInfo) => {
setNutritionTrackedDays(addDayTrackedFromPredictionHelper(nutritionTrackedDays, predictionNutritionInfo))
setFormInputMicronutrients([]);
}

const value = { nutritionTrackedDays, formInputMicronutrients,
addDayTracked, updateDayTracked, getDayTracked,
addFormInputMicronutrients, updateFormInputMicronutrients, deleteFormInputMicronutrients,
nutritionTrackedDaysSummary,
nutritionTrackedDaysView, dayTrackedSearchResult,
filterDayTracked, removeDayTracked, clearDayTrackedFilter,
setDefaultNutritionTrackedDaysValues, setDefaultNutritionTrackedDaysSummaryValues, updateNutritionTrackedDaysAndSummary }
setDefaultNutritionTrackedDaysValues, setDefaultNutritionTrackedDaysSummaryValues, updateNutritionTrackedDaysAndSummary,
addDayTrackedFromPrediction }

return (
<NutritionTrackerContext.Provider
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, useState, useEffect } from "react";

import { validateAddDayTracked, validateUpdateDayTracked,
import { validatePredictionInfo, validateAddDayTracked, validateUpdateDayTracked,
validateFilterNutritionTrackedDays, validateRemoveNutritionTrackedDay } from "../../../utils/validations/nutrition-tracker.validations";
import { calculateSummary } from "../../../utils/calculations/nutrition-tracker.calculations";

Expand All @@ -9,6 +9,24 @@ import { DEFAULT_MICRONUTRIENT } from "../../../utils/constants/nutrition-tracke
// TODO: sort the records by date
// helper functions

const addDayTrackedFromPredictionHelper = (nutritionTrackedDays, predictionNutritionInfo) => {
if (validatePredictionInfo(nutritionTrackedDays, predictionNutritionInfo)) return nutritionTrackedDays

return [
...nutritionTrackedDays,
{
dateTracked: String(predictionNutritionInfo.dateTracked),
calories: Number(predictionNutritionInfo.calories),
macronutrients: {
carbohydrates: Number(predictionNutritionInfo.macronutrients.carbohydrates),
protein: Number(predictionNutritionInfo.macronutrients.protein),
fat: Number(predictionNutritionInfo.macronutrients.fat),
},
micronutrients: predictionNutritionInfo.micronutrients
}
]
}

const addMicronutrientsToTrackedDayInfoHelper = (formInputMicronutrients, trackedDayInfo) => {
return {
...trackedDayInfo,
Expand Down Expand Up @@ -181,6 +199,8 @@ export const NutritionTrackerContext = createContext({
updateFormInputMicronutrients: () => {},
deleteFormInputMicronutrients: () => {},

addDayTrackedFromPrediction: () => {},

nutritionTrackedDaysSummary: {},
// nutritionTrackedDaysSummary structure:
// {
Expand Down Expand Up @@ -272,12 +292,18 @@ export const NutritionTrackerProvider = ({ children }) => {
setNutritionTrackedDaysView(nutritionTrackedDays)
}

const addDayTrackedFromPrediction = (predictionNutritionInfo) => {
setNutritionTrackedDays(addDayTrackedFromPredictionHelper(nutritionTrackedDays, predictionNutritionInfo))
setFormInputMicronutrients([]);
}

const value = { nutritionTrackedDays, formInputMicronutrients,
addDayTracked, updateDayTracked, getDayTracked,
addFormInputMicronutrients, updateFormInputMicronutrients, deleteFormInputMicronutrients,
nutritionTrackedDaysSummary,
nutritionTrackedDaysView, dayTrackedSearchResult,
filterDayTracked, removeDayTracked, clearDayTrackedFilter }
filterDayTracked, removeDayTracked, clearDayTrackedFilter,
addDayTrackedFromPrediction }

return (
<NutritionTrackerContext.Provider
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { validateAddDayTracked, validateUpdateDayTracked,
import { validatePredictionInfo, validateAddDayTracked, validateUpdateDayTracked,
validateFilterNutritionTrackedDays, validateRemoveNutritionTrackedDay
} from "../../../utils/validations/nutrition-tracker.validations";
import { calculateSummary } from "../../../utils/calculations/nutrition-tracker.calculations";
Expand All @@ -10,6 +10,24 @@ import { NUTRITION_TRACKER_ACTION_TYPES } from "./nutrition-tracker.types";
// TODO: sort the records by date
// helper functions

const addDayTrackedFromPredictionHelper = (nutritionTrackedDays, predictionNutritionInfo) => {
if (validatePredictionInfo(nutritionTrackedDays, predictionNutritionInfo)) return nutritionTrackedDays

return [
...nutritionTrackedDays,
{
dateTracked: String(predictionNutritionInfo.dateTracked),
calories: Number(predictionNutritionInfo.calories),
macronutrients: {
carbohydrates: Number(predictionNutritionInfo.macronutrients.carbohydrates),
protein: Number(predictionNutritionInfo.macronutrients.protein),
fat: Number(predictionNutritionInfo.macronutrients.fat),
},
micronutrients: predictionNutritionInfo.micronutrients
}
]
}

const addMicronutrientsToTrackedDayInfoHelper = (formInputMicronutrients, trackedDayInfo) => {
return {
...trackedDayInfo,
Expand Down Expand Up @@ -191,4 +209,10 @@ export const setNutritionTrackedDaysView = (nutritionTrackedDaysView) => {

export const setNutritionTrackedDaysSummary = (nutritionTrackedDaysSummary) => {
return createAction(NUTRITION_TRACKER_ACTION_TYPES.SET_NUTRITION_TRACKED_DAYS_SUMMARY, nutritionTrackedDaysSummary)
}

export const addDayTrackedFromPrediction = (nutritionTrackedDays, predictionNutritionInfo) => {
const newNutritionTrackedDays = addDayTrackedFromPredictionHelper(nutritionTrackedDays, predictionNutritionInfo)

return createAction(NUTRITION_TRACKER_ACTION_TYPES.SET_NUTRITION_TRACKED_DAYS, newNutritionTrackedDays)
}
70 changes: 69 additions & 1 deletion src/utils/validations/nutrition-tracker.validations.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,74 @@ import { REGEX_PATTERNS } from "./regex.constants";

// nutrition tracker validation functions

export const validatePredictionInfo = (nutritionTrackedDays, predictionNutritionInfo) => {
// check that trackedDayInfo's day doesn't exist in nutritionTrackedDays
const trackedDayExists = nutritionTrackedDays.find((nutritionTrackedDay) => {
return nutritionTrackedDay.dateTracked === predictionNutritionInfo.dateTracked;
});

if (trackedDayExists) {
errorOnTrackedDayExists();

return true;
}

// check if macronutrients data types are valid
if (!(REGEX_PATTERNS.floatNumbers.test(String(predictionNutritionInfo.calories))) ||
Number(predictionNutritionInfo.calories) < 0 ||
!(REGEX_PATTERNS.floatNumbers.test(String(predictionNutritionInfo.macronutrients.carbohydrates))) ||
Number(predictionNutritionInfo.macronutrients.carbohydrates) < 0 ||
!(REGEX_PATTERNS.floatNumbers.test(String(predictionNutritionInfo.macronutrients.protein))) ||
Number(predictionNutritionInfo.macronutrients.protein) < 0 ||
!(REGEX_PATTERNS.floatNumbers.test(String(predictionNutritionInfo.macronutrients.fat))) ||
Number(predictionNutritionInfo.macronutrients.fat) < 0) {

errorOnInvalidMacronutrientInputs();

return true;
}

// check if micronutrients are valid
// check if micronutrients data types are valid
const invalidMicronutrients = predictionNutritionInfo.micronutrients.find(micronutrient => {
if (String(micronutrient.name).length > 50 || String(micronutrient.unit).length > 5 ) {

errorOnInvalidMicronutrientInput();

return true;
}

if (!(REGEX_PATTERNS.floatNumbers.test(String(micronutrient.amount))) ||
Number(micronutrient.amount) < 0) {

errorOnInvalidMicronutrientInput();

return true;
}

return false;
});

if (invalidMicronutrients) return true;

// check if micronutrients are not empty
const emptyMicronutrients = predictionNutritionInfo.micronutrients.find(micronutrient => {
if (String(micronutrient.name) === "" || String(micronutrient.amount) === "" ||
String(micronutrient.unit) === "") {

errorOnEmptyMicronutrients();

return true;
}

return false;
});

if (emptyMicronutrients) return true;

return false;
}

export const validateAddDayTracked = (nutritionTrackedDays, trackedDayInfo) => {
// check that trackedDayInfo's day doesn't exist in nutritionTrackedDays
const trackedDayExists = nutritionTrackedDays.find((nutritionTrackedDay) => {
Expand Down Expand Up @@ -71,7 +139,7 @@ export const validateAddDayTracked = (nutritionTrackedDays, trackedDayInfo) => {
if (emptyMicronutrients) return true;

return false;
};
}

export const validateUpdateDayTracked = (nutritionTrackedDays, updatedTrackedDayInfo) => {
// check that updatedTrackedDayInfo exists in nutritionTrackedDays
Expand Down

0 comments on commit 3d5a951

Please sign in to comment.