Line data Source code
1 : // Copyright 2026 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/storage/app_data.dart';
6 : import 'package:app_finance/_classes/structure/bill_app_data.dart';
7 : import 'package:app_finance/_classes/structure/budget_app_data.dart';
8 : import 'package:app_finance/_classes/structure/currency/exchange.dart';
9 : import 'package:app_finance/_classes/structure/navigation/app_route.dart';
10 : import 'package:app_finance/_configs/custom_text_theme.dart';
11 : import 'package:app_finance/_configs/theme_helper.dart';
12 : import 'package:app_finance/_ext/build_context_ext.dart';
13 : import 'package:app_finance/design/generic/base_swipe_widget.dart';
14 : import 'package:app_finance/design/wrapper/background_wrapper.dart';
15 : import 'package:app_finance/design/wrapper/number_wrapper.dart';
16 : import 'package:app_finance/design/wrapper/row_widget.dart';
17 : import 'package:app_finance/design/wrapper/tap_widget.dart';
18 : import 'package:app_finance/design/wrapper/text_wrapper.dart';
19 : import 'package:app_finance/pages/_interfaces/abstract_page_state.dart';
20 : import 'package:app_finance/pages/bill/widgets/bill_line_widget.dart';
21 : import 'package:material_ui/material_ui.dart';
22 : import 'package:intl/intl.dart';
23 :
24 : class BillScopeViewPage extends StatefulWidget {
25 : final String search;
26 : final String uuid;
27 :
28 0 : const BillScopeViewPage({
29 : super.key,
30 : required this.search,
31 : required this.uuid,
32 : });
33 :
34 0 : @override
35 0 : BillScopeViewPageState createState() => BillScopeViewPageState();
36 : }
37 :
38 : class BillScopeViewPageState extends AbstractPageState<BillScopeViewPage> {
39 0 : @override
40 0 : String getTitle() => DateFormat.yMMMM().format(DateTime.parse(widget.search));
41 :
42 0 : @override
43 : String getButtonName() => '';
44 :
45 0 : @override
46 : Widget buildButton(BuildContext context, BoxConstraints constraints) => const SizedBox.shrink();
47 :
48 0 : bool getContentFilter(BillAppData item) {
49 0 : final budgetMatch = item.category == widget.uuid;
50 0 : final startDate = DateTime.parse(widget.search);
51 0 : final startDateMatch = item.createdAt.isAfter(startDate);
52 0 : final endDate = DateTime(startDate.year, startDate.month + 1, startDate.day);
53 0 : final endDateMatch = item.createdAt.isBefore(endDate);
54 : return !(budgetMatch && startDateMatch && endDateMatch);
55 : }
56 :
57 0 : List<BillAppData> getContent() =>
58 0 : state.getStream<BillAppData>(AppDataType.bills, filter: getContentFilter).toList().cast<BillAppData>();
59 :
60 0 : @override
61 : Widget buildContent(BuildContext context, BoxConstraints constraints) {
62 0 : final items = getContent();
63 0 : final exchange = Exchange(store: state);
64 0 : final item = (state.getByUuid(widget.uuid) as BudgetAppData).clone();
65 0 : item.amount = 0.0;
66 0 : item.details = 0.0;
67 0 : for (var bill in items) {
68 0 : item.amount += exchange.reform(bill.details, bill.currency, item.currency);
69 : }
70 0 : final width = ThemeHelper.getWidth(context, 2, constraints);
71 0 : final textTheme = context.textTheme;
72 0 : final indent = ThemeHelper.getIndent();
73 0 : final txtWidth = ThemeHelper.getTextWidth(Text(item.detailsFormatted, style: textTheme.numberMedium));
74 0 : return Padding(
75 0 : padding: EdgeInsets.all(indent),
76 0 : child: Column(
77 0 : children: [
78 0 : Column(
79 0 : children: [
80 0 : RowWidget(
81 : indent: indent,
82 0 : alignment: AppDesign.getAlignment<MainAxisAlignment>(),
83 : maxWidth: width,
84 0 : chunk: [null, txtWidth + 2 * indent],
85 0 : children: [
86 0 : [
87 0 : Row(
88 0 : children: [
89 0 : Icon(item.icon, color: item.color, size: 20),
90 : ThemeHelper.wIndent,
91 0 : TextWrapper(
92 0 : item.title,
93 0 : style: textTheme.headlineMedium,
94 : ),
95 : ],
96 : ),
97 0 : if (item.description.isNotEmpty)
98 0 : TextWrapper(
99 0 : item.description,
100 0 : style: textTheme.numberSmall,
101 : ),
102 : ],
103 0 : [
104 0 : Align(
105 : alignment: Alignment.centerRight,
106 0 : child: NumberWidget(
107 0 : item.detailsFormatted,
108 0 : colorScheme: context.colorScheme,
109 0 : style: textTheme.numberMedium,
110 : ),
111 : ),
112 : ],
113 : ],
114 : ),
115 : ],
116 : ),
117 : ThemeHelper.hIndent05,
118 : const Divider(height: 2),
119 0 : Expanded(
120 0 : child: ListView.builder(
121 : scrollDirection: Axis.vertical,
122 : shrinkWrap: true,
123 0 : itemCount: items.length + 1,
124 0 : itemBuilder: (BuildContext context, index) {
125 0 : if (index >= items.length) {
126 : return ThemeHelper.formEndBox;
127 : }
128 0 : BillAppData item = items[index];
129 0 : final account = state.getByUuid(item.account);
130 0 : final budget = state.getByUuid(item.category);
131 0 : return BackgroundWrapper(
132 : index: index,
133 0 : child: BaseSwipeWidget(
134 : routePath: AppRoute.billEditRoute,
135 0 : uuid: item.uuid!,
136 0 : child: TapWidget(
137 : tooltip: '',
138 0 : route: RouteSettings(name: AppRoute.billViewRoute, arguments: {routeArguments.uuid: item.uuid}),
139 0 : child: BillLineWidget(
140 0 : width: width - 2 * indent,
141 0 : uuid: item.uuid ?? '',
142 0 : title: item.title,
143 0 : details: item.detailsFormatted,
144 0 : description: item.description,
145 0 : color: item.color ?? Colors.transparent,
146 0 : icon: item.icon ?? Icons.question_mark,
147 0 : descriptionColor: account?.color ?? Colors.transparent,
148 0 : iconTooltip: budget?.title ?? '?',
149 : ),
150 : ),
151 : ),
152 : );
153 : },
154 : ),
155 : ),
156 : ],
157 : ),
158 : );
159 : }
160 : }
|