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/structure/account_app_data.dart';
7 : import 'package:app_finance/_configs/account_type.dart';
8 : import 'package:app_finance/_classes/controller/focus_controller.dart';
9 : import 'package:app_finance/_classes/storage/app_preferences.dart';
10 : import 'package:app_finance/_configs/theme_helper.dart';
11 : import 'package:app_finance/_ext/build_context_ext.dart';
12 : import 'package:app_finance/design/form/checkbox_input.dart';
13 : import 'package:app_finance/design/wrapper/input_wrapper.dart';
14 : import 'package:app_finance/design/wrapper/text_wrapper.dart';
15 : import 'package:app_finance/pages/_interfaces/abstract_add_page.dart';
16 : import 'package:app_finance/design/form/date_time_input.dart';
17 : import 'package:app_finance/design/button/full_sized_button_widget.dart';
18 : import 'package:app_finance/design/form/simple_input.dart';
19 : import 'package:app_finance/design/wrapper/row_widget.dart';
20 : import 'package:app_finance/design/wrapper/single_scroll_wrapper.dart';
21 : import 'package:material_ui/material_ui.dart';
22 : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
23 :
24 : class AccountAddPage extends AbstractAddPage {
25 : final String? title;
26 : final String? description;
27 : final String? type;
28 : final Currency? currency;
29 : final DateTime? validTillDate;
30 : final double? balance;
31 : final IconData? icon;
32 : final MaterialColor? color;
33 :
34 1 : const AccountAddPage({
35 : super.key,
36 : this.title,
37 : this.description,
38 : this.type,
39 : this.currency,
40 : this.validTillDate,
41 : this.balance,
42 : this.icon,
43 : this.color,
44 : });
45 :
46 1 : @override
47 1 : AccountAddPageState createState() => AccountAddPageState();
48 : }
49 :
50 : class AccountAddPageState<T extends AccountAddPage> extends AbstractAddPageState<T> {
51 : late FocusController focus;
52 : late TextEditingController title;
53 : late TextEditingController description;
54 : String? type;
55 : Currency? currency;
56 : DateTime? validTillDate;
57 : DateTime balanceUpdateDate = DateTime.now();
58 : late TextEditingController balance;
59 : IconData? icon;
60 : MaterialColor? color;
61 : bool skip = false;
62 :
63 1 : @override
64 : void initState() {
65 2 : focus = FocusController();
66 4 : title = TextEditingController(text: widget.title);
67 4 : description = TextEditingController(text: widget.description);
68 3 : type = widget.type;
69 3 : validTillDate = widget.validTillDate;
70 1 : final currencyId = AppPreferences.get(AppPreferences.prefCurrency);
71 4 : currency = widget.currency ?? CurrencyProvider.find(currencyId);
72 4 : balance = TextEditingController(text: widget.balance != null ? widget.balance!.toString() : '');
73 3 : icon = widget.icon;
74 3 : color = widget.color;
75 1 : super.initState();
76 : }
77 :
78 1 : @override
79 : void dispose() {
80 2 : title.dispose();
81 2 : description.dispose();
82 2 : balance.dispose();
83 2 : focus.dispose();
84 1 : super.dispose();
85 : }
86 :
87 1 : @override
88 2 : String getTitle() => AppLocale.labels.createAccountHeader;
89 :
90 1 : @override
91 : bool hasFormErrors() {
92 11 : setState(() => hasError = type == null || type?.isEmpty == true || title.text.isEmpty || currency == null);
93 1 : return hasError;
94 : }
95 :
96 1 : @override
97 : void updateStorage() {
98 1 : if (currency != null) {
99 2 : CurrencyProvider.pin(currency!);
100 : }
101 3 : state.add(AccountAppData(
102 2 : title: title.text,
103 1 : type: type ?? AppAccountType.cash.toString(),
104 2 : description: description.text,
105 3 : details: double.tryParse(balance.text) ?? 0.0,
106 : progress: 1.0,
107 1 : color: color ?? Colors.red,
108 1 : currency: currency,
109 : hidden: false,
110 1 : icon: icon,
111 1 : closedAt: validTillDate,
112 1 : createdAt: balanceUpdateDate,
113 1 : skip: skip,
114 : ));
115 : }
116 :
117 1 : @override
118 2 : String getButtonName() => AppLocale.labels.createAccountTooltip;
119 :
120 1 : @override
121 : Widget buildButton(BuildContext context, BoxConstraints constraints) {
122 1 : NavigatorState nav = Navigator.of(context);
123 1 : return FullSizedButtonWidget(
124 : constraints: constraints,
125 1 : controller: focus,
126 2 : onPressed: () => triggerActionButton(nav),
127 1 : title: getButtonName(),
128 : icon: Icons.save,
129 : );
130 : }
131 :
132 1 : @override
133 : Widget buildContent(BuildContext context, BoxConstraints constraints) {
134 1 : final TextTheme textTheme = context.textTheme;
135 1 : double indent = ThemeHelper.getIndent(2);
136 1 : double width = ThemeHelper.getWidth(context, 6, constraints);
137 :
138 1 : return SingleScrollWrapper(
139 1 : controller: focus,
140 1 : child: Container(
141 1 : margin: EdgeInsets.fromLTRB(indent, indent, indent, 240),
142 1 : child: Column(
143 1 : crossAxisAlignment: AppDesign.getAlignment(),
144 1 : children: [
145 1 : InputWrapper.select(
146 : isRequired: true,
147 1 : value: type,
148 2 : title: AppLocale.labels.accountType,
149 2 : tooltip: AppLocale.labels.accountTypeTooltip,
150 1 : showError: hasError && type == null,
151 1 : options: AccountType.getList(),
152 4 : onChange: (value) => setState(() => type = value),
153 : ),
154 1 : InputWrapper.text(
155 : isRequired: true,
156 1 : controller: title,
157 2 : title: AppLocale.labels.title,
158 2 : tooltip: AppLocale.labels.titleAccountTooltip,
159 1 : showError: hasError && title.text.isEmpty,
160 : ),
161 1 : RowWidget(
162 : indent: indent,
163 1 : maxWidth: width + indent,
164 : chunk: const [80, 80, null],
165 1 : children: [
166 1 : [
167 1 : InputWrapper.icon(
168 1 : value: icon,
169 2 : title: AppLocale.labels.icon,
170 0 : onChange: (value) => setState(() => icon = value),
171 : ),
172 : ],
173 1 : [
174 1 : InputWrapper.color(
175 1 : value: color,
176 2 : title: AppLocale.labels.color,
177 0 : onChange: (value) => setState(() => color = value),
178 : ),
179 : ],
180 1 : [
181 1 : InputWrapper.text(
182 1 : controller: description,
183 2 : title: AppLocale.labels.details,
184 2 : tooltip: AppLocale.labels.detailsTooltip,
185 : ),
186 : ],
187 : ],
188 : ),
189 1 : InputWrapper.currency(
190 : isRequired: true,
191 1 : showError: hasError && currency == null,
192 1 : value: currency,
193 2 : title: AppLocale.labels.currency,
194 2 : tooltip: AppLocale.labels.currencyTooltip,
195 4 : onChange: (value) => setState(() => currency = value),
196 : ),
197 3 : if (!AccountType.contains(type ?? '', [AppAccountType.account, AppAccountType.cash]))
198 1 : InputWrapper(
199 : type: NamedInputType.ymSelector,
200 2 : title: AppLocale.labels.validTillDate,
201 1 : value: validTillDate,
202 0 : onChange: (value) => setState(() => validTillDate = value),
203 : ),
204 1 : InputWrapper.text(
205 2 : title: AppLocale.labels.balance,
206 2 : tooltip: AppLocale.labels.balanceTooltip,
207 1 : controller: balance,
208 : inputType: const TextInputType.numberWithOptions(decimal: true),
209 1 : formatter: [
210 1 : SimpleInputFormatter.filterDouble,
211 : ],
212 : ),
213 1 : CheckboxInput(
214 2 : label: AppLocale.labels.skipFromTotals,
215 1 : value: skip,
216 0 : onChanged: (value) => setState(() => skip = value),
217 : constraints: constraints,
218 : ),
219 1 : ThemeHelper.hIndent2x,
220 1 : RowWidget(
221 : indent: indent,
222 1 : maxWidth: width + indent,
223 : chunk: const [null, 20],
224 1 : children: [
225 1 : [
226 1 : TextWrapper(
227 2 : AppLocale.labels.balanceDate,
228 1 : style: textTheme.bodyLarge,
229 : ),
230 : ],
231 1 : [
232 1 : Tooltip(
233 2 : message: AppLocale.labels.balanceDateTooltip,
234 : child: const Icon(Icons.info_outline),
235 : ),
236 : ]
237 : ],
238 : ),
239 1 : DateTimeInput(
240 : width: width,
241 1 : value: balanceUpdateDate,
242 0 : setState: (value) => setState(() => balanceUpdateDate = value),
243 : ),
244 1 : ThemeHelper.hIndent2x,
245 : ],
246 : ),
247 : ),
248 : );
249 : }
250 : }
|