main
1import 'package:blood_pressure_app/features/input/forms/form_base.dart';
2import 'package:blood_pressure_app/l10n/app_localizations.dart';
3import 'package:blood_pressure_app/model/storage/settings_store.dart';
4import 'package:flutter/material.dart';
5import 'package:intl/intl.dart';
6import 'package:provider/provider.dart';
7
8/// Input to allow date and time input.
9class DateTimeForm extends FormBase<DateTime> {
10 /// Create input to allow date and time input.
11 const DateTimeForm({super.key,
12 super.initialValue,
13 });
14
15 @override
16 FormStateBase<DateTime, DateTimeForm> createState() => DateTimeFormState();
17}
18
19/// State of a [DateTimeForm].
20class DateTimeFormState extends FormStateBase<DateTime, DateTimeForm> {
21 late DateTime _time;
22
23 String? _error;
24
25 @override
26 void initState() {
27 super.initState();
28 _time = widget.initialValue ?? DateTime.now();
29 }
30
31 @override
32 DateTime? save() => validate() ? _time : null;
33
34 @override
35 bool isEmptyInputFocused() => false;
36
37 @override
38 bool validate() {
39 if (context.read<Settings>().validateInputs && _time.isAfter(DateTime.now())) {
40 setState(() {
41 _error = AppLocalizations.of(context)!.errTimeAfterNow;
42 });
43 return false;
44 } else if (_error != null) {
45 setState(() {
46 _error = null;
47 });
48 }
49 return true;
50 }
51
52 @override
53 void fillForm(DateTime? value) => setState(() {
54 _time = value ?? DateTime.now();
55 });
56
57 Future<void> _openDatePicker() async {
58 final now = DateTime.now();
59 final date = await showDatePicker(
60 context: context,
61 initialDate: _time,
62 firstDate: DateTime.fromMillisecondsSinceEpoch(1),
63 lastDate: _time.isAfter(now) ? _time : now,
64 );
65 if (date == null) return;
66 setState(() => _time = date.copyWith(
67 hour: _time.hour,
68 minute: _time.minute,
69 ));
70
71 }
72
73 Future<void> _openTimePicker() async {
74 final timeOfDay = await showTimePicker(
75 context: context,
76 initialTime: TimeOfDay.fromDateTime(_time),
77 );
78 if (timeOfDay == null) return;
79 setState(() => _time = _time.copyWith(
80 hour: timeOfDay.hour,
81 minute: timeOfDay.minute,
82 ));
83 }
84
85 Widget _buildInput(String content, void Function() onTap, String label, [String? error]) => Expanded(
86 child: InputDecorator(
87 decoration: InputDecoration(
88 labelText: label,
89 error: error == null ? null : Text(error),
90 ),
91 child: GestureDetector(
92 onTap: onTap,
93 child: Text(content, style: Theme.of(context).textTheme.bodyLarge)
94 ),
95 ),
96 );
97
98 @override
99 Widget build(BuildContext context) {
100 final date = DateFormat('yyyy-MM-dd').format(_time);
101 final timeOfDay = DateFormat('HH:mm').format(_time);
102 return Row(
103 children: [
104 _buildInput(date, _openDatePicker, AppLocalizations.of(context)!.date),
105 SizedBox(width: 8,),
106 _buildInput(timeOfDay, _openTimePicker, AppLocalizations.of(context)!.time, _error),
107 ],
108 );
109 }
110}