main
1import 'package:blood_pressure_app/features/input/forms/form_base.dart';
2import 'package:blood_pressure_app/features/settings/tiles/color_picker_list_tile.dart';
3import 'package:flutter/material.dart';
4import 'package:blood_pressure_app/l10n/app_localizations.dart';
5
6/// Form to enter freeform text and select color.
7class NoteForm extends FormBase<(String?, Color?)> {
8 /// Create form to enter freeform text and select color.
9 const NoteForm({super.key,
10 super.initialValue,
11 });
12
13 @override
14 NoteFormState createState() => NoteFormState();
15}
16
17/// State of form to enter freeform text and select color.
18class NoteFormState extends FormStateBase<(String?, Color?), NoteForm> {
19 late final TextEditingController _controller;
20
21 final FocusNode _focusNode = FocusNode();
22
23 Color? _color;
24
25 @override
26 void initState() {
27 super.initState();
28 _controller = TextEditingController(text: widget.initialValue?.$1);
29 _color = widget.initialValue?.$2;
30 }
31
32 @override
33 void dispose() {
34 _focusNode.dispose();
35 _controller.dispose();
36 super.dispose();
37 }
38
39 @override
40 bool validate() => true;
41
42 @override
43 (String?, Color?)? save() {
44 final String? text = _controller.text.isEmpty ? null : _controller.text;
45 if (text == null && _color == null) return null;
46 return (text, _color);
47 }
48
49 @override
50 bool isEmptyInputFocused() => _focusNode.hasFocus && _controller.text.isEmpty;
51
52 @override
53 void fillForm((String?, Color?)? value) => setState(() {
54 if (value == null) {
55 _controller.text = '';
56 _color = null;
57 } else {
58 if (value.$1 != null) _controller.text = value.$1!;
59 if (value.$2 != null) _color = value.$2!;
60 }
61 });
62
63 @override
64 Widget build(BuildContext context) => Column(
65 children: [
66 Padding(
67 padding: const EdgeInsets.symmetric(vertical: 16),
68 child: TextFormField(
69 focusNode: _focusNode,
70 controller: _controller,
71 decoration: InputDecoration(
72 labelText: AppLocalizations.of(context)!.addNote,
73 ),
74 minLines: 1,
75 maxLines: 4,
76 ),
77 ),
78 InputDecorator(
79 decoration: InputDecoration(
80 contentPadding: EdgeInsets.zero,
81 ),
82 child: ColorSelectionListTile(
83 title: Text(AppLocalizations.of(context)!.color, style: Theme.of(context).textTheme.bodyLarge,),
84 onMainColorChanged: (Color value) => setState(() {
85 _color = (value == Colors.transparent) ? null : value;
86 }),
87 initialColor: _color ?? Colors.transparent,
88 ),
89 ),
90 ],
91 );
92}