diff --git a/apps/admin/data/fitai.db b/apps/admin/data/fitai.db
index d626798..f8a1bd1 100644
Binary files a/apps/admin/data/fitai.db and b/apps/admin/data/fitai.db differ
diff --git a/apps/mobile/src/components/ScanFoodModal.tsx b/apps/mobile/src/components/ScanFoodModal.tsx
index fbeffb9..a69d322 100644
--- a/apps/mobile/src/components/ScanFoodModal.tsx
+++ b/apps/mobile/src/components/ScanFoodModal.tsx
@@ -5,6 +5,7 @@ import {
KeyboardAvoidingView,
Modal,
Platform,
+ ScrollView,
StyleSheet,
Text,
TextInput,
@@ -244,166 +245,184 @@ export function ScanFoodModal({
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.resultContainer}
>
-
-
-
-
-
- {notFound ? "Barcode Not Found" : "Food Details"}
-
-
-
-
-
- {!notFound && foodData ? (
- <>
-
-
-
-
-
-
- {foodData.name}
- {foodData.brand ? (
- {foodData.brand}
- ) : null}
- {foodData.servingSize}
-
-
-
- {foodData.caloriesPerServing}
-
- kcal per serving
-
-
-
- Number of Servings
-
-
- setServings(
- String(
- Math.max(0.5, parseFloat(servings || "1") - 0.5),
- ),
- )
- }
- style={styles.servingsButton}
- >
-
-
-
-
- setServings(String(parseFloat(servings || "1") + 0.5))
- }
- style={styles.servingsButton}
- >
-
-
-
-
- >
- ) : (
- <>
-
- We could not find this product in OpenFoodFacts.
-
-
- Food Name
-
+
+
+
-
- Calories
-
-
- kcal
-
- >
- )}
-
-
- Meal Type
-
- {MEAL_TYPES.map((type) => {
- const active = mealType === type;
- return (
- setMealType(type)}
- style={[
- styles.mealTypeChip,
- active && styles.mealTypeChipActive,
- ]}
- >
-
- {type.charAt(0).toUpperCase() + type.slice(1)}
-
-
- );
- })}
-
+
+
+ {notFound ? "Barcode Not Found" : "Food Details"}
+
+
-
+
+
+ {!notFound && foodData ? (
+ <>
+
+
+
+
+
+
+ {foodData.name}
+
+ {[foodData.brand, foodData.servingSize]
+ .filter(Boolean)
+ .join(" • ")}
+
+
+
+
+ {foodData.caloriesPerServing}
+
+
+ kcal per serving
+
+
+
+
+ Servings
+
+
+ setServings(
+ String(
+ Math.max(
+ 0.5,
+ parseFloat(servings || "1") - 0.5,
+ ),
+ ),
+ )
+ }
+ style={styles.servingsButton}
+ >
+
+
+
+
+ setServings(
+ String(parseFloat(servings || "1") + 0.5),
+ )
+ }
+ style={styles.servingsButton}
+ >
+
+
+
+
+ >
+ ) : (
+ <>
+
+ We could not find this product in OpenFoodFacts.
+
+
+ Food Name
+
+
+ Calories
+
+
+ kcal
+
+ >
+ )}
+
+
+ Meal Type
+
+ {MEAL_TYPES.map((type) => {
+ const active = mealType === type;
+ return (
+ setMealType(type)}
+ style={[
+ styles.mealTypeChip,
+ active && styles.mealTypeChipActive,
+ ]}
+ >
+
+ {type.charAt(0).toUpperCase() + type.slice(1)}
+
+
+ );
+ })}
+
+
+
+
+
+
Total Calories
{getTotalCalories()} kcal
-
-
-
- Scan Again
-
+
+
+ Reject
+
-
-
-
- {notFound ? "Add Manual" : "Add to Diary"}
-
-
-
+
+ Add to Count
+
+
+
)}
@@ -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,