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