main
1import 'package:blood_pressure_app/components/confirm_deletion_dialoge.dart';
2import 'package:blood_pressure_app/components/nullable_text.dart';
3import 'package:blood_pressure_app/components/pressure_text.dart';
4import 'package:blood_pressure_app/data_util/entry_context.dart';
5import 'package:blood_pressure_app/model/storage/storage.dart';
6import 'package:flutter/material.dart';
7import 'package:flutter_bloc/flutter_bloc.dart';
8import 'package:blood_pressure_app/l10n/app_localizations.dart';
9import 'package:health_data_store/health_data_store.dart';
10import 'package:intl/intl.dart';
11
12/// Display of a blood pressure measurement data.
13class MeasurementListRow extends StatelessWidget {
14 /// Create a display of a measurements.
15 const MeasurementListRow({super.key,
16 required this.data,
17 required this.onRequestEdit,
18 });
19
20 /// The measurement to display.
21 final FullEntry data;
22
23 /// Called when the user taps on the edit icon.
24 final void Function() onRequestEdit; // TODO: consider removing in favor of context methods
25
26 @override
27 Widget build(BuildContext context) {
28 final localizations = AppLocalizations.of(context)!;
29 final settings = context.watch<Settings>();
30 final formatter = DateFormat(settings.dateFormatString);
31 return ExpansionTile(
32 // Leading color possible
33 title: _buildRow(formatter),
34 childrenPadding: const EdgeInsets.only(bottom: 10),
35 backgroundColor: data.color == null ? null : Color(data.color!).withAlpha(30),
36 collapsedShape: data.color == null ? null : Border(
37 left: BorderSide(color: Color(data.color!), width: 8),
38 ),
39 children: [
40 ListTile(
41 subtitle: Text(formatter.format(data.time)),
42 title: Text(localizations.timestamp),
43 trailing: Row(
44 mainAxisSize: MainAxisSize.min,
45 children: [
46 IconButton(
47 onPressed: onRequestEdit,
48 icon: const Icon(Icons.edit),
49 tooltip: localizations.edit,
50 ),
51 IconButton(
52 onPressed: () => context.deleteEntry(data),
53 icon: const Icon(Icons.delete),
54 tooltip: localizations.delete,
55 ),
56 ],
57 ),
58 ),
59 if (data.note?.isNotEmpty ?? false)
60 ListTile(
61 title: Text(localizations.note),
62 subtitle: Text(data.note!),
63 ),
64 for (final MedicineIntake intake in data.$3)
65 ListTile(
66 title: Text(intake.medicine.designation),
67 subtitle: Text('${intake.dosis.mg}mg'), // TODO: setting for unit
68 leading: Icon(Icons.medication,
69 color: intake.medicine.color == null ? null : Color(intake.medicine.color!)),
70 trailing: IconButton(
71 onPressed: () async {
72 final messenger = ScaffoldMessenger.of(context);
73 final intakeRepo = RepositoryProvider.of<MedicineIntakeRepository>(context);
74 if (!settings.confirmDeletion || await showConfirmDeletionDialoge(context)) {
75 await intakeRepo.remove(intake);
76 }
77 messenger.removeCurrentSnackBar();
78 messenger.showSnackBar(SnackBar(
79 content: Text(localizations.deletionConfirmed),
80 action: SnackBarAction(
81 label: localizations.btnUndo,
82 onPressed: () => intakeRepo.add(intake),
83 ),
84 ));
85 },
86 icon: const Icon(Icons.delete),
87 ),
88 ),
89 ],
90 );
91 }
92
93 Row _buildRow(DateFormat formatter) => Row(
94 children: [
95 Expanded(
96 flex: 30,
97 child: PressureText(data.sys),
98 ),
99 Expanded(
100 flex: 30,
101 child: PressureText(data.dia),
102 ),
103 Expanded(
104 flex: 30,
105 child: NullableText((data.pul?.toString())),
106 ),
107 Expanded(
108 flex: 10,
109 child: data.$3.isNotEmpty ? Icon(Icons.medication) : SizedBox.shrink(),
110 ),
111 ],
112 );
113}