Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved.
2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file.
3 :
4 : import 'package:app_finance/_classes/herald/app_design.dart';
5 : import 'package:app_finance/_classes/herald/app_locale.dart';
6 : import 'package:app_finance/_classes/storage/app_data.dart';
7 : import 'package:app_finance/design/form/currency_selector_code.dart';
8 : import 'package:app_finance/design/form/date_input.dart';
9 : import 'package:app_finance/design/form/list_selector_item.dart';
10 : import 'package:app_finance/_configs/screen_helper.dart';
11 : import 'package:app_finance/_configs/theme_helper.dart';
12 : import 'package:app_finance/_ext/build_context_ext.dart';
13 : import 'package:app_finance/design/form/color_selector.dart';
14 : import 'package:app_finance/design/form/currency_selector.dart';
15 : import 'package:app_finance/design/form/icon_selector.dart';
16 : import 'package:app_finance/design/form/list_account_selector.dart';
17 : import 'package:app_finance/design/form/list_budget_selector.dart';
18 : import 'package:app_finance/design/form/list_selector.dart';
19 : import 'package:app_finance/design/form/month_year_input.dart';
20 : import 'package:app_finance/design/form/simple_input.dart';
21 : import 'package:app_finance/design/wrapper/required_widget.dart';
22 : import 'package:app_finance/design/wrapper/text_wrapper.dart';
23 : import 'package:flutter/material.dart';
24 : import 'package:flutter/services.dart';
25 :
26 : enum NamedInputType {
27 : accountSelector,
28 : budgetSelector,
29 : colorSelector,
30 : currencySelector,
31 : currencyShort,
32 : iconSelector,
33 : listSelector,
34 : textInput,
35 : ymSelector,
36 : dateSelector,
37 : }
38 :
39 : class InputWrapper extends StatelessWidget {
40 : final NamedInputType type;
41 : final bool isRequired;
42 : final bool showError;
43 : final String title;
44 : final List<dynamic>? options;
45 : final Function? onChange;
46 : final String? tooltip;
47 : final TextEditingController? controller;
48 : final dynamic value;
49 : final List<TextInputFormatter>? formatter;
50 : final AppData? state;
51 : final double? width;
52 : final TextInputType? inputType;
53 :
54 6 : Key getKey() => ValueKey(key?.hashCode ?? '$title $tooltip');
55 :
56 1 : const InputWrapper({
57 : super.key,
58 : required this.type,
59 : required this.title,
60 : this.tooltip,
61 : this.controller,
62 : this.onChange,
63 : this.options,
64 : this.value,
65 : this.formatter,
66 : this.isRequired = false,
67 : this.showError = false,
68 : this.state,
69 : this.width,
70 : this.inputType,
71 : });
72 :
73 1 : const InputWrapper.text({
74 : super.key,
75 : this.type = NamedInputType.textInput,
76 : required this.title,
77 : required this.controller,
78 : this.tooltip,
79 : this.isRequired = false,
80 : this.showError = false,
81 : this.onChange,
82 : this.options,
83 : this.value,
84 : this.formatter,
85 : this.state,
86 : this.width,
87 : this.inputType,
88 : });
89 :
90 1 : const InputWrapper.select({
91 : super.key,
92 : this.type = NamedInputType.listSelector,
93 : required this.title,
94 : required this.options,
95 : required this.onChange,
96 : required this.value,
97 : this.tooltip,
98 : this.isRequired = false,
99 : this.showError = false,
100 : this.controller,
101 : this.formatter,
102 : this.state,
103 : this.width,
104 : this.inputType,
105 : });
106 :
107 1 : const InputWrapper.icon({
108 : super.key,
109 : this.type = NamedInputType.iconSelector,
110 : required this.title,
111 : required this.onChange,
112 : this.controller,
113 : this.tooltip,
114 : this.isRequired = false,
115 : this.showError = false,
116 : this.options,
117 : this.value,
118 : this.formatter,
119 : this.state,
120 : this.width,
121 : this.inputType,
122 : });
123 :
124 1 : const InputWrapper.color({
125 : super.key,
126 : this.type = NamedInputType.colorSelector,
127 : required this.title,
128 : required this.onChange,
129 : this.controller,
130 : this.tooltip,
131 : this.isRequired = false,
132 : this.showError = false,
133 : this.options,
134 : this.value,
135 : this.formatter,
136 : this.state,
137 : this.width,
138 : this.inputType,
139 : });
140 :
141 1 : const InputWrapper.currency({
142 : super.key,
143 : this.type = NamedInputType.currencySelector,
144 : required this.value,
145 : required this.title,
146 : required this.onChange,
147 : this.controller,
148 : this.tooltip,
149 : this.isRequired = false,
150 : this.showError = false,
151 : this.options,
152 : this.formatter,
153 : this.state,
154 : this.width,
155 : this.inputType,
156 : });
157 :
158 1 : @override
159 : Widget build(BuildContext context) {
160 1 : final screenState = ScreenHelper.state();
161 : final min = screenState.isRight || screenState.isWearable;
162 1 : String? hint = min ? title : tooltip;
163 : Color? hintColor;
164 1 : if (isRequired && min) {
165 0 : if (showError) {
166 0 : hint = '$hint [!] ${AppLocale.labels.isRequired}';
167 0 : hintColor = context.colorScheme.primary;
168 : } else {
169 0 : hint = '$hint*';
170 : }
171 : }
172 1 : return Column(
173 1 : mainAxisAlignment: AppDesign.getAlignment<MainAxisAlignment>(),
174 1 : crossAxisAlignment: AppDesign.getAlignment(),
175 1 : children: [
176 : if (!min)
177 1 : isRequired
178 4 : ? RequiredWidget(title: title, showError: showError)
179 4 : : TextWrapper(title, style: context.textTheme.bodyLarge),
180 2 : switch (type) {
181 2 : NamedInputType.textInput => SimpleInput(
182 1 : key: getKey(),
183 1 : controller: controller!,
184 : tooltip: hint,
185 : withLabel: min,
186 : hintColor: hintColor,
187 1 : formatter: formatter,
188 1 : type: inputType ?? TextInputType.text,
189 : ),
190 2 : NamedInputType.listSelector => ListSelector<ListSelectorItem>(
191 1 : key: getKey(),
192 3 : value: value != null ? ListSelectorItem(id: value, name: '') : null,
193 1 : tooltip: tooltip,
194 : hintText: hint,
195 : hintColor: hintColor,
196 1 : options: options as List<ListSelectorItem>,
197 4 : setState: (ListSelectorItem? v) => onChange?.call(v?.id),
198 : withLabel: min,
199 : ),
200 2 : NamedInputType.iconSelector => IconSelector(
201 1 : key: getKey(),
202 1 : value: value != null ? IconSelectorItem(value, name: value.toString()) : null,
203 0 : setState: (v) => onChange?.call((v as IconSelectorItem?)?.value),
204 : hintText: hint,
205 : withLabel: min,
206 : ),
207 2 : NamedInputType.colorSelector => ColorSelector(
208 1 : key: getKey(),
209 1 : value: value,
210 0 : setState: (v) => onChange?.call(v),
211 : withLabel: min,
212 : ),
213 2 : NamedInputType.currencySelector => BaseCurrencySelector(
214 1 : key: getKey(),
215 3 : value: value != null ? BaseListSelectorItem(value) : null,
216 4 : setState: (v) => onChange?.call((v as BaseListSelectorItem?)?.item),
217 : withLabel: min,
218 1 : tooltip: tooltip,
219 1 : hintText: tooltip,
220 : ),
221 2 : NamedInputType.currencyShort => CodeCurrencySelector(
222 1 : key: getKey(),
223 3 : value: value != null ? CodeCurrencySelectorItem(value) : null,
224 4 : setState: (v) => onChange?.call((v as CodeCurrencySelectorItem?)?.item),
225 : withLabel: min,
226 1 : tooltip: tooltip,
227 1 : hintText: tooltip,
228 : ),
229 2 : NamedInputType.ymSelector => MonthYearInput(
230 1 : key: getKey(),
231 1 : value: value,
232 1 : setState: onChange!,
233 : withLabel: min,
234 1 : labelText: title,
235 : ),
236 1 : NamedInputType.dateSelector => DateInput(
237 0 : value: value,
238 0 : setState: onChange!,
239 : withLabel: min,
240 : ),
241 2 : NamedInputType.accountSelector => ListAccountSelector(
242 1 : key: getKey(),
243 3 : value: value != null ? ListAccountSelectorItem(item: value) : null,
244 : hintText: hint,
245 1 : tooltip: tooltip,
246 1 : state: state!,
247 4 : setState: (v) => onChange?.call((v as ListAccountSelectorItem?)?.item),
248 1 : width: width!,
249 : withLabel: min,
250 2 : options: options?.cast() ?? [],
251 : ),
252 2 : NamedInputType.budgetSelector => ListBudgetSelector(
253 1 : key: getKey(),
254 3 : value: value != null ? ListBudgetSelectorItem(item: value) : null,
255 : hintText: hint,
256 1 : tooltip: tooltip,
257 1 : state: state!,
258 4 : setState: (v) => onChange?.call((v as ListBudgetSelectorItem?)?.item),
259 1 : width: width!,
260 : withLabel: min,
261 : ),
262 : },
263 1 : ThemeHelper.hIndent2x,
264 : ],
265 : );
266 : }
267 : }
|