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_locale.dart';
5 : import 'package:app_finance/_classes/herald/app_start_of_month.dart';
6 : import 'package:app_finance/_classes/storage/app_data.dart';
7 : import 'package:app_finance/_classes/structure/currency/exchange.dart';
8 : import 'package:app_finance/_classes/structure/navigation/app_route.dart';
9 : import 'package:app_finance/_configs/theme_helper.dart';
10 : import 'package:app_finance/_ext/build_context_ext.dart';
11 : import 'package:app_finance/_ext/date_time_ext.dart';
12 : import 'package:app_finance/_ext/string_ext.dart';
13 : import 'package:app_finance/components/_core/component_data.dart';
14 : import 'package:app_finance/components/widgets/account_widget.dart';
15 : import 'package:app_finance/components/widgets/bill_widget.dart';
16 : import 'package:app_finance/components/widgets/budget_widget.dart';
17 : import 'package:app_finance/components/widgets/payment_widget.dart';
18 : import 'package:app_finance/design/form/list_selector_item.dart';
19 : import 'package:app_finance/design/form/list_selector.dart';
20 : import 'package:app_finance/design/form/simple_input.dart';
21 : import 'package:app_finance/design/generic/base_widget.dart';
22 : import 'package:material_ui/material_ui.dart';
23 : import 'package:provider/provider.dart';
24 :
25 : enum ComponentRecentType {
26 : account,
27 : budget,
28 : bill,
29 : invoice,
30 : goals,
31 : payment,
32 : }
33 :
34 : class ComponentRecent extends StatelessWidget {
35 : static const count = 'count';
36 :
37 : final ComponentData data;
38 :
39 1 : const ComponentRecent(this.data, {super.key});
40 :
41 0 : @override
42 : Widget build(BuildContext context) {
43 0 : double indent = ThemeHelper.getIndent(0.5);
44 0 : EdgeInsets margin = EdgeInsets.all(indent);
45 0 : ComponentRecentType? widgetType = data[componentData.type]?.toString().toEnum(ComponentRecentType.values);
46 0 : final limit = switch (data[count].runtimeType) {
47 0 : String => (data[count] as String).toInt(),
48 0 : double => (data[count] as double).toInt(),
49 0 : int => data[count],
50 : _ => 7,
51 : };
52 0 : DateTime startingDay = DateTime.now().getStartingDay(AppStartOfMonth.get());
53 0 : return Consumer<AppData>(builder: (context, appState, _) {
54 0 : final exchange = Exchange(store: appState);
55 0 : return LayoutBuilder(builder: (context, constraints) {
56 0 : final width = constraints.maxWidth - indent * 4;
57 0 : return Flex(
58 : direction: Axis.horizontal,
59 0 : children: [
60 : switch (widgetType) {
61 0 : ComponentRecentType.account => AccountWidget(
62 : margin: margin,
63 0 : title: '${AppLocale.labels.accountHeadline}, ${AppLocale.labels.total}',
64 0 : state: appState.get(AppDataType.accounts),
65 : limit: limit,
66 : route: AppRoute.accountRoute,
67 0 : tooltip: AppLocale.labels.accountTooltip,
68 : width: width,
69 0 : )..exchange = exchange,
70 0 : ComponentRecentType.budget => BudgetWidget(
71 : margin: margin,
72 0 : title: '${AppLocale.labels.budgetHeadline}, ${AppLocale.labels.left}',
73 0 : state: appState.get(AppDataType.budgets),
74 : limit: limit,
75 : route: AppRoute.budgetRoute,
76 0 : tooltip: AppLocale.labels.budgetTooltip,
77 : width: width,
78 0 : )..exchange = exchange,
79 0 : ComponentRecentType.bill => BillWidget(
80 : margin: margin,
81 0 : title: '${AppLocale.labels.billHeadline}, ${startingDay.fullMonth()}',
82 0 : state: appState.get(AppDataType.bills),
83 : limit: limit,
84 : route: AppRoute.billRoute,
85 0 : tooltip: AppLocale.labels.billTooltip,
86 : width: width,
87 : ),
88 0 : ComponentRecentType.goals => BaseWidget(
89 : margin: margin,
90 0 : title: AppLocale.labels.goalHeadline,
91 0 : state: appState.get(AppDataType.goals),
92 : limit: limit,
93 : route: AppRoute.goalRoute,
94 : routeList: AppRoute.goalViewRoute,
95 0 : tooltip: AppLocale.labels.goalTooltip,
96 : width: width,
97 : ),
98 0 : ComponentRecentType.invoice => BaseWidget(
99 : margin: margin,
100 0 : title: '${AppLocale.labels.invoiceHeadline} / ${AppLocale.labels.transferHeadline}',
101 0 : state: appState.get(AppDataType.invoice),
102 : limit: limit,
103 : routeList: AppRoute.invoiceViewRoute,
104 : route: null,
105 0 : tooltip: AppLocale.labels.invoiceHeadline,
106 : width: width,
107 : ),
108 0 : ComponentRecentType.payment => PaymentWidget(
109 0 : data: appState.getList(AppDataType.payments).cast(),
110 : state: appState,
111 : margin: margin,
112 : width: width,
113 : ),
114 : _ => ThemeHelper.emptyBox,
115 : },
116 : ],
117 : );
118 : });
119 : });
120 : }
121 : }
122 :
123 : class ComponentRecentForm extends StatefulWidget {
124 : final ComponentData data;
125 : final Function adjust;
126 :
127 0 : const ComponentRecentForm(this.data, {super.key, required this.adjust});
128 :
129 0 : @override
130 0 : ComponentRecentFormState createState() => ComponentRecentFormState();
131 : }
132 :
133 : class ComponentRecentFormState extends State<ComponentRecentForm> {
134 : final _controller = TextEditingController();
135 : late String? _option;
136 :
137 0 : @override
138 : initState() {
139 0 : super.initState();
140 0 : _controller.text = (widget.data[ComponentRecent.count] ?? 7).toString();
141 0 : _option = widget.data[componentData.type];
142 : }
143 :
144 0 : @override
145 : dispose() {
146 0 : _controller.dispose();
147 0 : super.dispose();
148 : }
149 :
150 0 : @override
151 : Widget build(BuildContext context) {
152 0 : return Container(
153 0 : color: context.colorScheme.surface,
154 0 : padding: EdgeInsets.only(left: ThemeHelper.getIndent(2), right: ThemeHelper.getIndent()),
155 : height: double.infinity,
156 0 : child: SingleChildScrollView(
157 0 : child: Column(
158 0 : children: [
159 : ThemeHelper.hIndent3x,
160 0 : ListSelector<ListSelectorItem>(
161 0 : setState: (value) {
162 0 : setState(() => _option = value?.id);
163 0 : widget.adjust(widget.data[componentData.order], {...widget.data, componentData.type: value?.id});
164 : },
165 0 : hintText: AppLocale.labels.cmpRecent,
166 0 : value: _option != null ? ListSelectorItem(id: _option!, name: '') : null,
167 0 : options: [
168 0 : ListSelectorItem(id: ComponentRecentType.account.toString(), name: AppLocale.labels.accountHeadline),
169 0 : ListSelectorItem(id: ComponentRecentType.budget.toString(), name: AppLocale.labels.budgetHeadline),
170 0 : ListSelectorItem(id: ComponentRecentType.bill.toString(), name: AppLocale.labels.billHeadline),
171 0 : ListSelectorItem(id: ComponentRecentType.invoice.toString(), name: AppLocale.labels.invoiceHeadline),
172 0 : ListSelectorItem(id: ComponentRecentType.payment.toString(), name: AppLocale.labels.paymentsHeadline),
173 0 : ListSelectorItem(id: ComponentRecentType.goals.toString(), name: AppLocale.labels.goalHeadline),
174 : ],
175 : ),
176 : ThemeHelper.hIndent,
177 0 : SimpleInput(
178 0 : controller: _controller,
179 : type: TextInputType.number,
180 0 : formatter: [SimpleInputFormatter.filterInt],
181 : withLabel: true,
182 0 : setState: (String value) {
183 0 : widget.adjust(
184 0 : widget.data[componentData.order],
185 0 : {...widget.data, ComponentRecent.count: value.isEmpty ? '0' : value},
186 : );
187 : },
188 0 : tooltip: AppLocale.labels.cmpRecentCount,
189 : ),
190 : ThemeHelper.hIndent,
191 : ],
192 : ),
193 : ),
194 : );
195 : }
196 : }
|