import { View, Text, TextInput, TouchableOpacity, StyleSheet, FlatList } from 'react-native'
import React, { useState, useCallback, useEffect } from 'react'
import { useLayoutEffect } from 'react'
import { useNavigation } from '@react-navigation/native'
import { useSQLiteContext } from 'expo-sqlite'
import { AntDesign } from '@expo/vector-icons'
import MacroSplitGraph from '../components/MacroSplitGraph';
import LoggedFoodItem from '../components/LoggedFoodItem'
import { useAppTheme } from '../hooks/colorScheme';
const QuickAdd = ({ navigation }) => {
const colors = useAppTheme();
const [foodName, setFoodName] = useState('');
const [calories, setCalories] = useState('');
const [protein, setProtein] = useState('');
const [carbs, setCarbs] = useState('');
const [fats, setFats] = useState('');
const [qty, setQty] = useState('');
const [multiplier, setMultiplier] = useState(1);
const values = {
protein: parseInt(protein) || 0,
carb: parseInt(carbs) || 0,
fat: parseInt(fats) || 0,
calories: (protein*4 + carbs*4 + fats*9) || 0
}
const getCalories = (protein, carbs, fats) => {
return ((protein || 0) * 4) + ((carbs || 0) * 4) + ((fats || 0) * 9);
}
const [customFoodData, setCustomFoodData] = useState([]);
const database = useSQLiteContext();
const insertIntoDB = async (name, calories, protein, carbs, fats, qty) => {
if (!name) {
alert("Name is required");
return;
}
if (qty <= 1) {
alert("Weight must be greater than 1");
return;
}
try {
await database.runAsync(
"INSERT INTO customfoods (name, qty, cal, protein, carb, fat) VALUES (?, ?, ?, ?, ?, ?);",
[
name,
parseInt(qty) || 100,
getCalories(protein, carbs, fats),
parseInt(protein) || 0,
parseInt(carbs) || 0,
parseInt(fats) || 0
]
);
clearFields();
await fetchCustomFood();
console.log("successfully added", name, "to customfoods");
}
catch (error) {
console.log(error);
alert("Error adding food, make sure to use a unique name");
}
}
const fetchCustomFood = async () => {
try {
//console.log("Attempting to fetch custom foods...");
if (!database) {
console.error("Database is not initialized");
return;
}
const results = await database.getAllAsync("SELECT * FROM customfoods;");
//console.log("Raw SQL results:", JSON.stringify(results));
if (Array.isArray(results)) {
//console.log("Number of items fetched:", results.length);
setCustomFoodData(results);
setMultiplier(customFoodData.qty/100 || 1)
} else {
console.error("Results is not an array:", typeof results);
}
}
catch (error) {
console.error("Error fetching data:", error);
setCustomFoodData([]);
}
}
useEffect(() => {
fetchCustomFood(); // Initial load
const unsubscribe = navigation.addListener('focus', fetchCustomFood);
return unsubscribe;
}, [navigation]);
React.useEffect(() => {
//console.log("customFoodData updated:", customFoodData.length, "items");
}, [customFoodData]);
const displayData = customFoodData.map(item => (
{
...item,
qty: item.qty,
cal: item.cal * (100 / item.qty),
protein: item.protein * (100 / item.qty),
carb: item.carb * (100 / item.qty),
fat: item.fat * (100 / item.qty),
}));
const clearFields = () => {
setFoodName('');
setCalories('');
setProtein('');
setCarbs('');
setFats('');
setQty('');
}
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
<View style={[styles.card, { backgroundColor: colors.boxes }]}>
<View style={styles.inputRow}>
<View style={[styles.nameInputContainer, { backgroundColor: colors.innerBoxes, flex: 1 }]}>
<TextInput
style={[styles.nameInput, {color: colors.text}]}
placeholder="Food Name"
value={foodName}
onChangeText={setFoodName}
placeholderTextColor={colors.text + '80'}
returnKeyType='done'
/>
</View>
<View style={[styles.qtyMainContainer, { backgroundColor: colors.innerBoxes, flex: 1, marginLeft: 8 }]}>
<TextInput
style={[styles.qtyInput, {color: colors.text}]}
placeholder="100g"
value={qty}
onChangeText={setQty}
placeholderTextColor={colors.text + '80'}
keyboardType="numeric"
returnKeyType='done'
/>
</View>
</View>
<View style={styles.topGraphic}>
<View style={styles.graphContainer}>
<MacroSplitGraph values={values}/>
</View>
<View style={styles.macroInfoContainer}>
<View style={styles.macroRow}>
<Text style={[styles.macroLabel, { color: colors.greenColor }]}>Protein</Text>
<View style={[styles.qtyContainer, { backgroundColor: colors.innerBoxes }]}>
<TextInput
style={[styles.qtyInput, {color: colors.text}]}
placeholder="0g"
value={protein}
onChangeText={setProtein}
placeholderTextColor={colors.text + '80'}
keyboardType="numeric"
returnKeyType='done'
/>
</View>
</View>
<View style={styles.macroRow}>
<Text style={[styles.macroLabel, { color: colors.blueColor }]}>Carbs</Text>
<View style={[styles.qtyContainer, { backgroundColor: colors.innerBoxes }]}>
<TextInput
style={[styles.qtyInput, {color: colors.text}]}
placeholder="0g"
value={carbs}
onChangeText={setCarbs}
placeholderTextColor={colors.text + '80'}
keyboardType="numeric"
returnKeyType='done'
/>
</View>
</View>
<View style={styles.macroRow}>
<Text style={[styles.macroLabel, { color: colors.yellowColor }]}>Fats</Text>
<View style={[styles.qtyContainer, { backgroundColor: colors.innerBoxes }]}>
<TextInput
style={[styles.qtyInput, {color: colors.text}]}
placeholder="0g"
value={fats}
onChangeText={setFats}
placeholderTextColor={colors.text + '80'}
keyboardType="numeric"
returnKeyType='done'
/>
</View>
</View>
</View>
</View>
<TouchableOpacity
onPress={() => insertIntoDB(foodName, parseInt(calories), parseInt(protein), parseInt(carbs), parseInt(fats), parseInt(qty))}
style={[styles.actionButton, { backgroundColor: 'transparent'}]}
>
<AntDesign name="pluscircleo" size={24} color={colors.accent} />
<Text style={{color: colors.accent, fontSize: 16, fontWeight: 'bold'}}>
Add New Food
</Text>
</TouchableOpacity>
</View>
<View style={styles.listContainer}>
<FlatList
data={displayData}
ListHeaderComponent={displayData.length > 0 ? () => (
<Text style={{color: colors.text, fontSize: 18, textAlign: 'center', marginBottom: 10}}>
Custom Foods
</Text>
) : null}
renderItem={({item, index}) => (
<LoggedFoodItem
item={item}
index={index}
iscustom={1}
fromQuickAdd={1}
/>
)}
keyExtractor={item => item.id?.toString() || Math.random().toString()}
contentContainerStyle={{
padding: 5,
gap: 5,
}}
ListEmptyComponent={() => (
<Text style={{
color: colors.text,
textAlign: 'center',
padding: 20,
fontSize: 16
}}>
No custom foods added yet
</Text>
)}
/>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
card: {
borderRadius: 20,
padding: 20,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 8,
elevation: 5,
},
topGraphic: {
gap: 16,
justifyContent: "space-between",
flexDirection: "row",
alignItems: "center",
},
graphContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
maxWidth: '50%',
},
macroInfoContainer: {
flex: 1,
gap: 8,
maxWidth: '50%',
},
macroRow: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingVertical: 4,
},
macroLabel: {
fontSize: 15,
fontWeight: '600',
width: '35%',
marginRight: 4,
},
qtyContainer: {
flex: 1,
borderRadius: 12,
overflow: 'hidden',
},
nameInputContainer: {
borderRadius: 12,
overflow: 'hidden',
},
qtyMainContainer: {
borderRadius: 12,
overflow: 'hidden',
},
qtyInput: {
fontSize: 16,
fontWeight: '600',
padding: 8,
textAlign: 'center',
},
nameInput: {
fontSize: 16,
fontWeight: '600',
padding: 8,
textAlign: 'center',
},
actionButton: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
padding: 5,
marginTop: 16,
gap: 8,
borderRadius: 12,
},
listContainer: {
flex: 1,
borderRadius: 20,
overflow: 'hidden',
},
inputRow: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 16,
},
});
export default QuickAdd;