Files
calorie-counter/mobile/src/components/FoodRow.tsx
Andris Enins 91cd18aec6 feat: initial implementation — all 35 requirements across phases 1-3
Backend (Spring Boot 3.2 / Java 21 / PostgreSQL):
- JWT auth with BCrypt password hashing
- User profile + Mifflin-St Jeor BMR calculator
- Food search + barcode via OpenFoodFacts API with local cache
- Meal CRUD with user data isolation and ownership checks
- AI photo analysis (OpenAI Vision) with confidence intervals
- AI correction feedback loop for personalisation
- Flyway DB migrations + RFC-7807 error responses

Mobile (React Native / TypeScript):
- Full navigation stack (Auth → Tabs → Home stack)
- Design tokens (WCAG 2.2 AA colours, 8px grid, 48px touch targets)
- 10 screens: Login, Register, Home, Search, Camera, AI Result, Edit Meal,
  Daily Details, History, Profile
- Confidence-aware calorie display (kcal ± range)
- Repeat last meal shortcut + macro tracking

Docs:
- docs/PLAN-AND-REQUIREMENTS.md
- docs/traceability.csv (35 requirements, all Implemented)
2026-05-18 21:56:13 +03:00

43 lines
1.2 KiB
TypeScript

// Generated by GitHub Copilot
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { FoodItem } from '../services/api';
import { Colors } from '../theme/colors';
import { Spacing } from '../theme/spacing';
interface FoodRowProps {
item: FoodItem;
onSelect: (item: FoodItem) => void;
}
/**
* Single food result row in the search screen.
* REQ-MOB-006
*/
export default function FoodRow({ item, onSelect }: FoodRowProps) {
return (
<TouchableOpacity
style={styles.row}
onPress={() => onSelect(item)}
accessibilityRole="button"
accessibilityLabel={`${item.name}, ${item.caloriesPer100g} calories per 100 grams`}
>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.kcal}>{item.caloriesPer100g} kcal / 100g</Text>
</TouchableOpacity>
);
}
const styles = StyleSheet.create({
row: {
minHeight: Spacing.touchTarget,
paddingHorizontal: Spacing.md,
paddingVertical: Spacing.sm,
borderBottomWidth: 1,
borderBottomColor: Colors.gray100,
justifyContent: 'center',
},
name: { fontSize: 16, fontWeight: '500', color: Colors.gray900 },
kcal: { fontSize: 13, color: Colors.gray500, marginTop: 2 },
});