fooder-app/lib/widgets/meal.dart

206 lines
5.9 KiB
Dart
Raw Permalink Normal View History

2023-07-29 19:21:02 +02:00
import 'package:flutter/material.dart';
2023-07-30 15:31:36 +02:00
import 'package:fooder/models/meal.dart';
import 'package:fooder/widgets/entry.dart';
2024-04-04 19:03:41 +02:00
import 'package:fooder/widgets/macro.dart';
2023-07-30 15:31:36 +02:00
import 'package:fooder/screens/edit_entry.dart';
import 'package:fooder/client.dart';
2023-07-29 19:21:02 +02:00
import 'dart:core';
2024-03-29 16:47:25 +01:00
class MealHeader extends StatelessWidget {
final Meal meal;
2024-03-30 14:07:10 +01:00
const MealHeader({super.key, required this.meal});
2024-03-29 16:47:25 +01:00
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
2024-04-04 19:03:41 +02:00
Expanded(
child: Padding(
padding: const EdgeInsets.all(8),
child: Text(
meal.name,
overflow: TextOverflow.fade,
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold,
),
),
2024-03-29 16:47:25 +01:00
),
),
],
);
}
}
2023-07-29 19:21:02 +02:00
class MealWidget extends StatelessWidget {
2024-03-30 14:07:10 +01:00
static const maxWidth = 920.0;
2024-03-29 16:47:25 +01:00
2023-07-29 19:21:02 +02:00
final Meal meal;
final ApiClient apiClient;
final Function() refreshParent;
2024-04-04 19:03:41 +02:00
final Function(String) showText;
2024-03-29 16:47:25 +01:00
final bool initiallyExpanded;
2023-07-29 19:21:02 +02:00
2024-03-30 14:07:10 +01:00
const MealWidget({
super.key,
required this.meal,
required this.apiClient,
required this.refreshParent,
required this.initiallyExpanded,
2024-04-04 19:03:41 +02:00
required this.showText,
2024-03-30 14:07:10 +01:00
});
2024-03-29 16:47:25 +01:00
2024-04-04 19:03:41 +02:00
Future<void> saveMeal(context) async {
TextEditingController textFieldController = TextEditingController();
textFieldController.text = meal.name;
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Save Meal'),
content: TextField(
controller: textFieldController,
decoration: const InputDecoration(hintText: "Meal template name"),
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
Navigator.pop(context);
},
),
IconButton(
icon: const Icon(Icons.save),
onPressed: () {
apiClient.saveMeal(meal, textFieldController.text);
Navigator.pop(context);
showText("Meal saved");
},
),
],
);
},
);
}
Future<void> _deleteMeal(Meal meal) async {
await apiClient.deleteMeal(meal.id);
}
Future<void> deleteMeal(context) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return AlertDialog(
title: const Text('Confirm deletion of the meal'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.cancel),
onPressed: () {
Navigator.pop(context);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
_deleteMeal(meal).then((_) => refreshParent());
Navigator.pop(context);
showText("Meal deleted");
},
),
],
);
},
);
2024-03-29 16:47:25 +01:00
}
Future<void> _editEntry(context, entry) async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditEntryScreen(
apiClient: apiClient,
entry: entry,
),
),
).then((_) => refreshParent());
}
2023-07-29 19:21:02 +02:00
@override
Widget build(BuildContext context) {
2024-03-29 16:47:25 +01:00
var theme = Theme.of(context);
var colorScheme = theme.colorScheme;
2024-03-30 14:07:10 +01:00
var widthAvail = MediaQuery.of(context).size.width;
var width = widthAvail > maxWidth ? maxWidth : widthAvail;
2024-03-29 16:47:25 +01:00
return Center(
2023-07-29 19:21:02 +02:00
child: Padding(
2024-03-29 16:47:25 +01:00
padding: const EdgeInsets.all(8),
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
2024-04-04 19:03:41 +02:00
child: Container(
constraints: BoxConstraints(maxWidth: width),
color: colorScheme.surface.withOpacity(0.2),
child: ExpansionTile(
iconColor: colorScheme.onSurface,
collapsedIconColor: colorScheme.onSurface,
initiallyExpanded: initiallyExpanded,
enableFeedback: true,
title: Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: <Widget>[
MealHeader(meal: meal),
const MacroHeaderWidget(
calories: true,
),
MacroEntryWidget(
protein: meal.protein,
carb: meal.carb,
fat: meal.fat,
calories: meal.calories,
),
2024-03-29 16:47:25 +01:00
],
),
2023-08-28 14:45:32 +02:00
),
2024-04-04 19:03:41 +02:00
children: <Widget>[
for (var (i, entry) in meal.entries.indexed)
ListTile(
title: EntryWidget(
entry: entry,
2023-08-28 14:45:32 +02:00
),
2024-04-04 19:03:41 +02:00
tileColor: i % 2 == 0
? colorScheme.surfaceVariant.withOpacity(0.1)
: Colors.transparent,
onTap: () => _editEntry(context, entry),
enableFeedback: true,
2024-03-29 16:47:25 +01:00
),
2024-04-04 19:03:41 +02:00
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
2024-03-29 16:47:25 +01:00
children: <Widget>[
2024-04-04 19:03:41 +02:00
IconButton(
icon: const Icon(Icons.save),
onPressed: () => saveMeal(context),
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () => deleteMeal(context),
),
2024-03-29 16:47:25 +01:00
],
),
2024-04-04 19:03:41 +02:00
],
2024-03-29 16:47:25 +01:00
),
2023-08-28 14:45:32 +02:00
),
2023-07-29 19:21:02 +02:00
),
),
2024-03-29 16:47:25 +01:00
);
2023-07-29 19:21:02 +02:00
}
}