fix: show dish calories in search and fix portion sheet layout crash
- DishSearchResult now carries calories_per_serving (backend entity + repo LEFT JOIN recipes / MIN / GROUP BY; Flutter model + fromJson) - _FoodTile.fromDish shows kcal/serving subtitle when available - _DishPortionSheet quick-select buttons: Row → Wrap to avoid BoxConstraints infinite-width crash inside DraggableScrollableSheet Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -7,12 +7,14 @@ class DishSearchResult {
|
||||
final String name;
|
||||
final String? imageUrl;
|
||||
final double avgRating;
|
||||
final double? caloriesPerServing;
|
||||
|
||||
const DishSearchResult({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.imageUrl,
|
||||
required this.avgRating,
|
||||
this.caloriesPerServing,
|
||||
});
|
||||
|
||||
factory DishSearchResult.fromJson(Map<String, dynamic> json) {
|
||||
@@ -21,6 +23,8 @@ class DishSearchResult {
|
||||
name: json['name'] as String,
|
||||
imageUrl: json['image_url'] as String?,
|
||||
avgRating: (json['avg_rating'] as num?)?.toDouble() ?? 0,
|
||||
caloriesPerServing:
|
||||
(json['calories_per_serving'] as num?)?.toDouble(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +484,9 @@ class _FoodTile extends StatelessWidget {
|
||||
size: 20, color: Colors.green),
|
||||
),
|
||||
title: dish.name,
|
||||
subtitle: null,
|
||||
subtitle: dish.caloriesPerServing != null
|
||||
? '${dish.caloriesPerServing!.toInt()} kcal / serving'
|
||||
: null,
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
@@ -635,27 +637,25 @@ class _DishPortionSheetState extends ConsumerState<_DishPortionSheet> {
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Quick-select portion buttons
|
||||
Row(
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
children: [
|
||||
for (final quickValue in [0.5, 1.0, 1.5, 2.0])
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: OutlinedButton(
|
||||
onPressed: () => _setPortions(quickValue),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 8),
|
||||
side: BorderSide(
|
||||
color: _selectedPortions == quickValue
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
width: _selectedPortions == quickValue ? 2 : 1,
|
||||
),
|
||||
OutlinedButton(
|
||||
onPressed: () => _setPortions(quickValue),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12, vertical: 8),
|
||||
side: BorderSide(
|
||||
color: _selectedPortions == quickValue
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
width: _selectedPortions == quickValue ? 2 : 1,
|
||||
),
|
||||
child: Text(quickValue % 1 == 0
|
||||
? quickValue.toInt().toString()
|
||||
: quickValue.toStringAsFixed(1)),
|
||||
),
|
||||
child: Text(quickValue % 1 == 0
|
||||
? quickValue.toInt().toString()
|
||||
: quickValue.toStringAsFixed(1)),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user