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