Recalculate the nutrition value based on serving size options.
Retrieve the PassioAttribute using the Passio ID. Within the food item, utilize the selectedQuantity and selectedServingUnit as the foundational values for obtaining nutrient values.
Some ServingUnits are included within the food item as servings options from SDK, each accompanied by a value and unit name. For example, an apple might have default servings like large with a value of 200, medium with a value of 172, and small with a value of 157.
Example
useRecalculateServingSize
import {
PassioSDK,
type ServingUnit,
} from '@passiolife/nutritionai-react-native-sdk-v2';
import { useEffect, useRef, useState } from 'react';
import {
calculateComputedWeightAmount,
getMacroNutrientsFormPassioFoodItem,
toFixed,
type Nutrients,
} from './recalculateUtils';
export interface RecalculateServingSizeProps {
passioID: string;
}
export const useRecalculateServingSize = ({
passioID,
}: RecalculateServingSizeProps) => {
// State to manage user input quantity
const [userInputQuantity, setUserInputQuantity] = useState('');
// State to manage selected serving value
const [selectedServingValue, setSelectedServingValue] = useState(0);
// State to manage selected serving unit
const [selectedServingUnit, setSelectedServingUnit] = useState('');
// State to store nutrients data
const [nutrients, setNutrition] = useState<Nutrients[]>();
// State to store serving units from PassioSDK
const [sdkServingUnits, setSDKServingUnits] = useState<ServingUnit[]>();
// Ref to store the base serving value for calculations
const sdkBaseServingValueRef = useRef(0);
// useEffect to initialize data on component mount
useEffect(() => {
// Function to initialize data from the PassioSDK
const initialize = async () => {
try {
const { foodItem } =
(await PassioSDK.getAttributesForPassioID(passioID)) || {};
if (!foodItem) return;
const { servingUnits, selectedQuantity, selectedUnit } = foodItem;
setSDKServingUnits(servingUnits);
setNutrition(getMacroNutrientsFormPassioFoodItem(foodItem));
const baseServingValue = calculateComputedWeightAmount(
selectedQuantity,
servingUnits,
selectedUnit
);
sdkBaseServingValueRef.current = baseServingValue;
setSelectedServingValue(baseServingValue);
setUserInputQuantity(selectedQuantity.toString());
setSelectedServingUnit(selectedUnit);
} catch (error) {
console.error('Error initializing:', error);
}
};
// Call the initialize function
initialize();
}, [passioID]);
// Function to handle selection of a serving unit
const onSelectServingItem = (servingUnit: ServingUnit) => {
setSelectedServingValue(servingUnit.value);
setSelectedServingUnit(servingUnit.unitName);
};
// Function to calculate updated nutrition value based on user input
const getUpdatedNutritionValue = (item: Nutrients) => {
const nutritionValue = item.unitMass?.value ?? 0;
const ratio = calculateRatio(nutritionValue);
const userInputServingSize =
userInputQuantity.length > 0 ? Number(userInputQuantity) : 1;
return toFixed(ratio * userInputServingSize);
};
// Function to calculate the ratio separately
const calculateRatio = (nutritionValue: number): number => {
return (
(nutritionValue * selectedServingValue) / sdkBaseServingValueRef.current
);
};
// Return the necessary values and functions
return {
nutrients,
onSelectServingItem,
sdkServingUnits,
selectedServingUnit,
getUpdatedNutritionValue,
setUserInputQuantity,
userInputQuantity,
};
};
RecalculateServingSize
import React from 'react';
import { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
import { toFixed } from './recalculateUtils';
import { FlatList } from 'react-native';
import { useRecalculateServingSize } from './useRecaculateServingSize';
export interface RecalculateServingSizeProps {
passioID: string;
}
export const RecalculateServingSize = ({
passioID,
}: RecalculateServingSizeProps) => {
// Destructuring values and functions from useRecalculateServingSize hook
const {
nutrients,
onSelectServingItem,
sdkServingUnits,
selectedServingUnit,
getUpdatedNutritionValue,
setUserInputQuantity,
userInputQuantity,
} = useRecalculateServingSize({
passioID: passioID,
});
return (
<View style={styles.container}>
{/* FlatList to display updated nutrition values */}
<FlatList
data={nutrients}
extraData={userInputQuantity}
renderItem={({ item }) => (
<View style={styles.nutrition}>
<Text style={styles.nutritionLabel}>{item.name}</Text>
<Text>
{getUpdatedNutritionValue(item)}
{item.unitMass?.unit}
</Text>
</View>
)}
/>
{/* Section to input total serving quantity */}
<View style={styles.nutritionTotalServing}>
<Text style={styles.nutritionLabel}>Total Serving</Text>
<TextInput
style={styles.totalServingInput}
placeholder="Total Serving"
keyboardType="numeric"
value={userInputQuantity.trim().toString()}
onChangeText={(value) => {
setUserInputQuantity(value.trim());
}}
/>
</View>
{/* FlatList to display serving units */}
<FlatList
data={sdkServingUnits}
horizontal
renderItem={({ item }) => (
<Pressable
onPress={() => {
onSelectServingItem(item);
}}
>
<Text
style={[
styles.servingUnit,
selectedServingUnit === item.unitName &&
styles.selectedServingUnit,
]}
>
{`${item.unitName} ${toFixed(item.value)}`}
</Text>
</Pressable>
)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1 },
nutrition: { flex: 1, flexDirection: 'row', padding: 16 },
servingUnit: { flexDirection: 'row', padding: 16 },
nutritionTotalServing: {
marginVertical: 16,
},
totalServingInput: { padding: 16, backgroundColor: 'white' },
selectedServingUnit: {
backgroundColor: 'blue',
color: 'white',
borderRadius: 24,
},
nutritionLabel: { flex: 1, textTransform: 'capitalize' },
});
Utility Methods
import type {
PassioFoodItem,
ServingUnit,
UnitMass,
} from '@passiolife/nutritionai-react-native-sdk-v2';
// Define the types of nutrients
export type NutrientsTypes =
| 'calories'
| 'protein'
| 'carbs'
| 'fat'
| 'saturatedFat'
| 'transFat'
| 'polyunsaturatedFat'
| 'sodium'
| 'fiber'
| 'sugar'
| 'sugarAdded'
| 'vitaminD'
| 'iron'
| 'potassium'
| 'vitaminA'
| 'vitaminC'
| 'alcohol'
| 'sugarAlcohol'
| 'vitaminB12'
| 'vitaminB12Added'
| 'vitaminB6'
| 'vitaminE'
| 'vitaminEAdded'
| 'phosphorus'
| 'iodine'
| 'cholesterol';
// Define the structure of individual nutrients
export interface Nutrients {
unitMass?: UnitMass;
name: NutrientsTypes;
}
// Get a single nutrient from Passio Food Item
export const getNutrient = (
foodItem: PassioFoodItem,
name: NutrientsTypes
): Nutrients | null => {
if (foodItem[name]) {
return {
name,
unitMass: foodItem[name] ?? undefined,
} as Nutrients;
} else {
return null;
}
};
// Get multiple nutrients from Passio FoodItem
const getNutrients = (
foodItem: PassioFoodItem,
nutrientNames: NutrientsTypes[]
): Nutrients[] => {
return nutrientNames
.map((name) => {
// General case for other nutrients
return getNutrient(foodItem, name);
})
.filter((item): item is Nutrients => !!item);
};
// Get micro nutrients from Passio FoodItem
export const getMicroNutrientsFormPassioFoodItem = (
foodItem: PassioFoodItem
): Nutrients[] => {
const microNutrientNames: NutrientsTypes[] = [
'saturatedFat',
'transFat',
'polyunsaturatedFat',
'sodium',
'fiber',
'sugar',
'sugarAdded',
'vitaminD',
'iron',
'potassium',
'vitaminA',
'alcohol',
'sugarAlcohol',
'vitaminB12',
'vitaminB12Added',
'vitaminB6',
'vitaminE',
'vitaminEAdded',
'phosphorus',
'iodine',
'cholesterol',
];
return getNutrients(foodItem, microNutrientNames);
};
// Get micro nutrients from Passio FoodItem
export const getMacroNutrientsFormPassioFoodItem = (
foodItem: PassioFoodItem
): Nutrients[] => {
const macros: NutrientsTypes[] = ['calories', 'carbs', 'protein', 'fat'];
return getNutrients(foodItem, macros);
};
// Function to format nutrient value
export const toFixed = (value?: number): number => {
return Number((value ?? 0).toFixed(2));
};
export function calculateComputedWeightAmount(
qty: number,
servingUnits: ServingUnit[],
unit: string
) {
const result = qty * calculateMassOfServingUnit(servingUnits, unit);
return result < 10 ? result : Math.ceil(result);
}
export function calculateMassOfServingUnit(
servingUnits: ServingUnit[],
selectedUnit: string
): number {
let unit = 1;
servingUnits?.forEach((value) => {
if (value.unitName === selectedUnit) {
unit = value.value;
}
});
return unit;
}
Last updated