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}