main
1import 'package:blood_pressure_app/features/data_picker/filter_button.dart';
2import 'package:blood_pressure_app/model/datarange_extension.dart';
3import 'package:blood_pressure_app/model/storage/interval_store.dart';
4import 'package:flutter/material.dart';
5import 'package:blood_pressure_app/l10n/app_localizations.dart';
6import 'package:health_data_store/health_data_store.dart';
7import 'package:intl/intl.dart';
8import 'package:provider/provider.dart';
9import 'package:week_of_year/date_week_extensions.dart';
10
11/// A selector for [IntervalStorage] values.
12///
13/// Allows selection [IntervalStorage.currentRange] and moving intervall wise
14/// in both directions.
15class IntervalPicker extends StatelessWidget {
16 /// Create a selector for [IntervalStorage] values.
17 const IntervalPicker({super.key,
18 required this.type,
19 this.customRangePickerCurrentDay,
20 });
21
22 /// Which range to display and modify.
23 final IntervalStoreManagerLocation type;
24
25 /// The day from which to start the custom date range picker.
26 ///
27 /// Defaults to the current day which is the desired value in all non-test scenarios.
28 final DateTime? customRangePickerCurrentDay;
29
30 @override
31 Widget build(BuildContext context) => Consumer<IntervalStoreManager>(
32 builder: (context, intervallStoreManager, _) {
33 final interval = intervallStoreManager.get(type);
34 final loc = AppLocalizations.of(context)!;
35 final start = interval.currentRange.start;
36 final end = interval.currentRange.end;
37 final String intervallDisplayText = switch (interval.stepSize) {
38 TimeStep.day => DateFormat.yMMMd().format(start),
39 TimeStep.week => loc.weekOfYear(start.weekOfYear, start.year),
40 TimeStep.month => DateFormat.yMMM().format(interval.currentRange.start),
41 TimeStep.year => DateFormat.y().format(interval.currentRange.start),
42 TimeStep.lifetime => '-',
43 TimeStep.last7Days || TimeStep.last30Days || TimeStep.custom =>
44 '${DateFormat.yMMMd().format(start)} - ${DateFormat.yMMMd().format(end)}',
45 };
46 return Column(
47 children: [
48 Text(intervallDisplayText, overflow: TextOverflow.ellipsis),
49 const SizedBox(height: 2),
50 Row(
51 children: [
52 MaterialButton(
53 onPressed: () => interval.moveDataRangeByStep(-1),
54 child: const Icon(Icons.chevron_left, size: 48),
55 ),
56 Expanded(
57 child: DropdownButton<TimeStep>(
58 value: interval.stepSize,
59 isExpanded: true,
60 onChanged: (TimeStep? value) async {
61 if (value == TimeStep.custom) {
62 final res = await showDateRangePicker(
63 context: context,
64 firstDate: DateTime.fromMillisecondsSinceEpoch(1),
65 lastDate: customRangePickerCurrentDay ?? DateTime.now(),
66 currentDate: customRangePickerCurrentDay,
67 );
68 if (res != null) {
69 interval.changeStepSize(value!);
70 final dateRange = res.dateRange.copyWith(
71 end: res.end.copyWith(hour: 23, minute: 59, second: 59),
72 );
73 interval.currentRange = dateRange;
74 }
75 } else if (value != null) {
76 interval.changeStepSize(value);
77 }
78 },
79 items: [
80 for (final TimeStep e in TimeStep.values)
81 DropdownMenuItem(value: e, child: Text(e.localize(loc))),
82 ]
83 ),
84 ),
85 FilterButton(interval: interval),
86 MaterialButton(
87 onPressed: () => interval.moveDataRangeByStep(1),
88 child: const Icon(Icons.chevron_right, size: 48),
89 ),
90 ],
91 ),
92 ],
93 );
94 },
95 );
96}