scan food

This commit is contained in:
echo 2026-03-31 16:55:55 +02:00
parent ca64a100b6
commit 21afb085e3
2 changed files with 222 additions and 177 deletions

Binary file not shown.

View File

@ -5,6 +5,7 @@ import {
KeyboardAvoidingView,
Modal,
Platform,
ScrollView,
StyleSheet,
Text,
TextInput,
@ -244,16 +245,29 @@ export function ScanFoodModal({
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.resultContainer}
>
<View style={styles.resultSheet}>
<View style={styles.resultHeader}>
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
<Ionicons name="close" size={28} color={theme.colors.gray900} />
<TouchableOpacity
onPress={handleReset}
style={styles.closeButton}
>
<Ionicons
name="scan"
size={24}
color={theme.colors.gray700}
/>
</TouchableOpacity>
<Text style={styles.resultTitle}>
{notFound ? "Barcode Not Found" : "Food Details"}
</Text>
<View style={{ width: 28 }} />
<View style={{ width: 24 }} />
</View>
<ScrollView
style={styles.resultScroll}
contentContainerStyle={styles.resultScrollContent}
showsVerticalScrollIndicator={false}
>
<View style={styles.foodCard}>
{!notFound && foodData ? (
<>
@ -262,31 +276,37 @@ export function ScanFoodModal({
colors={theme.gradients.success}
style={styles.foodIcon}
>
<Ionicons name="restaurant" size={32} color="#fff" />
<Ionicons name="restaurant" size={28} color="#fff" />
</LinearGradient>
</View>
<Text style={styles.foodName}>{foodData.name}</Text>
{foodData.brand ? (
<Text style={styles.servingSize}>{foodData.brand}</Text>
) : null}
<Text style={styles.servingSize}>{foodData.servingSize}</Text>
<Text style={styles.servingMeta}>
{[foodData.brand, foodData.servingSize]
.filter(Boolean)
.join(" • ")}
</Text>
<View style={styles.caloriesBadge}>
<Text style={styles.caloriesValue}>
{foodData.caloriesPerServing}
</Text>
<Text style={styles.caloriesLabel}>kcal per serving</Text>
<Text style={styles.caloriesLabel}>
kcal per serving
</Text>
</View>
<View style={styles.servingsContainer}>
<Text style={styles.label}>Number of Servings</Text>
<Text style={styles.label}>Servings</Text>
<View style={styles.servingsInput}>
<TouchableOpacity
onPress={() =>
setServings(
String(
Math.max(0.5, parseFloat(servings || "1") - 0.5),
Math.max(
0.5,
parseFloat(servings || "1") - 0.5,
),
),
)
}
@ -306,7 +326,9 @@ export function ScanFoodModal({
/>
<TouchableOpacity
onPress={() =>
setServings(String(parseFloat(servings || "1") + 0.5))
setServings(
String(parseFloat(servings || "1") + 0.5),
)
}
style={styles.servingsButton}
>
@ -321,7 +343,7 @@ export function ScanFoodModal({
</>
) : (
<>
<Text style={styles.servingSize}>
<Text style={styles.servingMeta}>
We could not find this product in OpenFoodFacts.
</Text>
@ -376,19 +398,17 @@ export function ScanFoodModal({
})}
</View>
</View>
</View>
</ScrollView>
<View style={styles.totalCalories}>
<View style={styles.footerSummary}>
<Text style={styles.totalLabel}>Total Calories</Text>
<Text style={styles.totalValue}>{getTotalCalories()} kcal</Text>
</View>
</View>
<View style={styles.buttonRow}>
<TouchableOpacity
onPress={handleReset}
style={styles.rescanButton}
>
<Text style={styles.rescanButtonText}>Scan Again</Text>
<TouchableOpacity onPress={onClose} style={styles.rejectButton}>
<Text style={styles.rejectButtonText}>Reject</Text>
</TouchableOpacity>
<TouchableOpacity
@ -399,12 +419,11 @@ export function ScanFoodModal({
colors={theme.gradients.success}
style={styles.confirmButton}
>
<Text style={styles.confirmButtonText}>
{notFound ? "Add Manual" : "Add to Diary"}
</Text>
<Text style={styles.confirmButtonText}>Add to Count</Text>
</LinearGradient>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
)}
</View>
@ -463,15 +482,32 @@ const styles = StyleSheet.create({
},
resultContainer: {
flex: 1,
backgroundColor: "rgba(0, 0, 0, 0.35)",
justifyContent: "flex-end",
},
resultSheet: {
backgroundColor: theme.colors.background,
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
maxHeight: "80%",
},
resultHeader: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
padding: 20,
paddingTop: 60,
paddingHorizontal: 20,
paddingVertical: 14,
backgroundColor: "#fff",
borderTopLeftRadius: 24,
borderTopRightRadius: 24,
borderBottomWidth: 1,
borderBottomColor: theme.colors.gray100,
},
resultScroll: {
flexGrow: 0,
},
resultScrollContent: {
paddingBottom: 12,
},
resultTitle: {
fontSize: 18,
@ -479,46 +515,47 @@ const styles = StyleSheet.create({
color: theme.colors.gray900,
},
foodCard: {
margin: 20,
padding: 24,
marginHorizontal: 16,
marginTop: 12,
padding: 16,
backgroundColor: "#fff",
borderRadius: 24,
borderRadius: 16,
alignItems: "center",
...theme.shadows.medium,
},
foodIconContainer: {
marginBottom: 16,
marginBottom: 10,
},
foodIcon: {
width: 80,
height: 80,
borderRadius: 40,
width: 64,
height: 64,
borderRadius: 32,
justifyContent: "center",
alignItems: "center",
},
foodName: {
fontSize: 24,
fontSize: 20,
fontWeight: "700",
color: theme.colors.gray900,
marginBottom: 8,
marginBottom: 4,
textAlign: "center",
},
servingSize: {
fontSize: 16,
servingMeta: {
fontSize: 14,
color: theme.colors.gray600,
marginBottom: 16,
marginBottom: 12,
textAlign: "center",
},
caloriesBadge: {
backgroundColor: theme.colors.gray50,
paddingHorizontal: 24,
paddingVertical: 16,
borderRadius: 16,
paddingHorizontal: 18,
paddingVertical: 10,
borderRadius: 12,
alignItems: "center",
marginBottom: 24,
marginBottom: 14,
},
caloriesValue: {
fontSize: 32,
fontSize: 26,
fontWeight: "700",
color: theme.colors.primary,
},
@ -529,11 +566,11 @@ const styles = StyleSheet.create({
},
servingsContainer: {
width: "100%",
marginBottom: 24,
marginBottom: 14,
},
mealTypeContainer: {
width: "100%",
marginBottom: 24,
marginBottom: 6,
},
mealTypeRow: {
flexDirection: "row",
@ -615,13 +652,18 @@ const styles = StyleSheet.create({
color: theme.colors.gray500,
},
totalCalories: {
width: "100%",
display: "none",
},
footerSummary: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingTop: 24,
paddingHorizontal: 20,
paddingTop: 10,
paddingBottom: 10,
borderTopWidth: 1,
borderTopColor: theme.colors.gray200,
backgroundColor: "#fff",
},
totalLabel: {
fontSize: 16,
@ -635,17 +677,20 @@ const styles = StyleSheet.create({
},
buttonRow: {
flexDirection: "row",
padding: 20,
paddingHorizontal: 20,
paddingTop: 8,
paddingBottom: 16,
gap: 12,
backgroundColor: "#fff",
},
rescanButton: {
rejectButton: {
flex: 1,
paddingVertical: 16,
borderRadius: 20,
backgroundColor: theme.colors.gray100,
alignItems: "center",
},
rescanButtonText: {
rejectButtonText: {
fontSize: 16,
fontWeight: "700",
color: theme.colors.gray700,