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 2 : 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 1 : @override
46 1 : 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 1 : @override
62 : void initState() {
63 2 : focus = FocusController();
64 4 : title = TextEditingController(text: widget.title);
65 4 : description = TextEditingController(text: widget.description);
66 3 : type = widget.type;
67 3 : validTillDate = widget.validTillDate;
68 4 : balance = TextEditingController(text: widget.balance != null ? widget.balance.toString() : '');
69 3 : icon = widget.icon;
70 3 : color = widget.color;
71 1 : final currencyId = AppPreferences.get(AppPreferences.prefCurrency);
72 4 : currency = widget.currency ?? CurrencyProvider.find(currencyId);
73 1 : super.initState();
74 : }
75 :
76 1 : @override
77 : void dispose() {
78 2 : title.dispose();
79 2 : description.dispose();
80 2 : balance.dispose();
81 2 : focus.dispose();
82 1 : super.dispose();
83 : }
84 :
85 1 : @override
86 2 : String getTitle() => AppLocale.labels.createAccountHeader;
87 :
88 1 : @override
89 : bool hasFormErrors() {
90 11 : setState(() => hasError = type == null || type?.isEmpty == true || title.text.isEmpty || currency == null);
91 1 : return hasError;
92 : }
93 :
94 1 : @override
95 : void updateStorage() {
96 1 : if (currency != null) {
97 2 : CurrencyProvider.pin(currency!);
98 : }
99 3 : state.add(AccountAppData(
100 2 : title: title.text,
101 1 : type: type ?? AppAccountType.cash.toString(),
102 2 : description: description.text,
103 3 : details: double.tryParse(balance.text) ?? 0.0,
104 : progress: 1.0,
105 1 : color: color ?? Colors.red,
106 1 : currency: currency,
107 : hidden: false,
108 1 : icon: icon,
109 1 : closedAt: validTillDate,
110 1 : createdAt: balanceUpdateDate,
111 : ));
112 : }
113 :
114 1 : @override
115 2 : String getButtonName() => AppLocale.labels.createAccountTooltip;
116 :
117 1 : @override
118 : Widget buildButton(BuildContext context, BoxConstraints constraints) {
119 1 : NavigatorState nav = Navigator.of(context);
120 1 : return FullSizedButtonWidget(
121 : constraints: constraints,
122 1 : controller: focus,
123 2 : onPressed: () => triggerActionButton(nav),
124 1 : title: getButtonName(),
125 : icon: Icons.save,
126 : );
127 : }
128 :
129 1 : @override
130 : Widget buildContent(BuildContext context, BoxConstraints constraints) {
131 1 : final TextTheme textTheme = context.textTheme;
132 1 : double indent = ThemeHelper.getIndent(2);
133 1 : double width = ThemeHelper.getWidth(context, 6, constraints);
134 :
135 1 : return SingleScrollWrapper(
136 1 : controller: focus,
137 1 : child: Container(
138 1 : margin: EdgeInsets.fromLTRB(indent, indent, indent, 240),
139 1 : child: Column(
140 1 : crossAxisAlignment: AppDesign.getAlignment(),
141 1 : children: [
142 1 : InputWrapper.select(
143 : isRequired: true,
144 1 : value: type,
145 2 : title: AppLocale.labels.accountType,
146 2 : tooltip: AppLocale.labels.accountTypeTooltip,
147 1 : showError: hasError && type == null,
148 1 : options: AccountType.getList(),
149 4 : onChange: (value) => setState(() => type = value),
150 : ),
151 1 : InputWrapper.text(
152 : isRequired: true,
153 1 : controller: title,
154 2 : title: AppLocale.labels.title,
155 2 : tooltip: AppLocale.labels.titleAccountTooltip,
156 1 : showError: hasError && title.text.isEmpty,
157 : ),
158 1 : RowWidget(
159 : indent: indent,
160 1 : maxWidth: width + indent,
161 : chunk: const [80, 80, null],
162 1 : children: [
163 1 : [
164 1 : InputWrapper.icon(
165 1 : value: icon,
166 2 : title: AppLocale.labels.icon,
167 0 : onChange: (value) => setState(() => icon = value),
168 : ),
169 : ],
170 1 : [
171 1 : InputWrapper.color(
172 1 : value: color,
173 2 : title: AppLocale.labels.color,
174 0 : onChange: (value) => setState(() => color = value),
175 : ),
176 : ],
177 1 : [
178 1 : InputWrapper.text(
179 1 : controller: description,
180 2 : title: AppLocale.labels.details,
181 2 : tooltip: AppLocale.labels.detailsTooltip,
182 : ),
183 : ],
184 : ],
185 : ),
186 1 : InputWrapper.currency(
187 : isRequired: true,
188 1 : showError: hasError && currency == null,
189 1 : value: currency,
190 2 : title: AppLocale.labels.currency,
191 2 : tooltip: AppLocale.labels.currencyTooltip,
192 4 : onChange: (value) => setState(() => currency = value),
193 : ),
194 3 : if (!AccountType.contains(type ?? '', [AppAccountType.account, AppAccountType.cash]))
195 1 : InputWrapper(
196 : type: NamedInputType.ymSelector,
197 2 : title: AppLocale.labels.validTillDate,
198 1 : value: validTillDate,
199 0 : onChange: (value) => setState(() => validTillDate = value),
200 : ),
201 1 : InputWrapper.text(
202 2 : title: AppLocale.labels.balance,
203 2 : tooltip: AppLocale.labels.balanceTooltip,
204 1 : controller: balance,
205 : inputType: const TextInputType.numberWithOptions(decimal: true),
206 1 : formatter: [
207 1 : SimpleInputFormatter.filterDouble,
208 : ],
209 : ),
210 1 : Row(
211 : mainAxisAlignment: MainAxisAlignment.spaceBetween,
212 1 : children: [
213 1 : TextWrapper(
214 2 : AppLocale.labels.balanceDate,
215 1 : style: textTheme.bodyLarge,
216 : ),
217 1 : Tooltip(
218 2 : message: AppLocale.labels.balanceDateTooltip,
219 : child: const Icon(Icons.info_outline),
220 : ),
221 : ],
222 : ),
223 1 : DateTimeInput(
224 : width: width,
225 1 : value: balanceUpdateDate,
226 0 : setState: (value) => setState(() => balanceUpdateDate = value),
227 : ),
228 1 : ThemeHelper.hIndent2x,
229 : ],
230 : ),
231 : ),
232 : );
233 : }
234 : }
|