LCOV - code coverage report
Current view: top level - lib/pages/account - account_view_page.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 123 0.0 %
Date: 2024-10-04 11:12:13 Functions: 0 0 -

          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 'dart:collection';
       5             : 
       6             : import 'package:app_finance/_classes/controller/iterator_controller.dart';
       7             : import 'package:app_finance/_classes/herald/app_design.dart';
       8             : import 'package:app_finance/_classes/herald/app_locale.dart';
       9             : import 'package:app_finance/_classes/controller/flow_state_machine.dart';
      10             : import 'package:app_finance/_classes/storage/app_data.dart';
      11             : import 'package:app_finance/_classes/structure/account_app_data.dart';
      12             : import 'package:app_finance/_classes/structure/account_summary_data.dart';
      13             : import 'package:app_finance/_classes/structure/bill_app_data.dart';
      14             : import 'package:app_finance/_classes/structure/currency/exchange.dart';
      15             : import 'package:app_finance/_classes/structure/invoice_app_data.dart';
      16             : import 'package:app_finance/_configs/custom_text_theme.dart';
      17             : import 'package:app_finance/_configs/theme_helper.dart';
      18             : import 'package:app_finance/_classes/structure/navigation/app_route.dart';
      19             : import 'package:app_finance/_ext/build_context_ext.dart';
      20             : import 'package:app_finance/design/wrapper/row_widget.dart';
      21             : import 'package:app_finance/design/wrapper/text_wrapper.dart';
      22             : import 'package:app_finance/pages/_interfaces/abstract_page_state.dart';
      23             : import 'package:app_finance/pages/account/widgets/account_line_widget.dart';
      24             : import 'package:app_finance/design/generic/base_line_widget.dart';
      25             : import 'package:app_finance/design/generic/base_list_infinite_widget.dart';
      26             : import 'package:app_finance/design/wrapper/confirmation_wrapper.dart';
      27             : import 'package:app_finance/design/wrapper/tab_widget.dart';
      28             : import 'package:flutter/material.dart';
      29             : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
      30             : import 'package:intl/intl.dart' as intl;
      31             : 
      32             : class AccountViewPage extends StatefulWidget {
      33             :   final String uuid;
      34             : 
      35           0 :   const AccountViewPage({
      36             :     super.key,
      37             :     required this.uuid,
      38             :   });
      39             : 
      40           0 :   @override
      41           0 :   AccountViewPageState createState() => AccountViewPageState();
      42             : }
      43             : 
      44             : class AccountViewPageState extends AbstractPageState<AccountViewPage> {
      45             :   late double width;
      46             :   int focus = 0;
      47             : 
      48           0 :   @override
      49             :   String getTitle() {
      50           0 :     final item = super.state.getByUuid(widget.uuid) as AccountAppData;
      51           0 :     return item.title;
      52             :   }
      53             : 
      54           0 :   @override
      55             :   String getButtonName() => '';
      56             : 
      57           0 :   @override
      58             :   Widget buildButton(BuildContext context, BoxConstraints constraints) {
      59           0 :     double indent = ThemeHelper.getIndent(4);
      60           0 :     NavigatorState nav = Navigator.of(context);
      61           0 :     return Container(
      62           0 :       margin: EdgeInsets.only(left: 2 * indent, right: 2 * indent),
      63           0 :       child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
      64           0 :         FloatingActionButton(
      65             :           heroTag: 'account_view_page_edit',
      66           0 :           onPressed: () => nav.pushNamed(AppRoute.accountEditRoute, arguments: {routeArguments.uuid: widget.uuid}),
      67           0 :           tooltip: AppLocale.labels.editAccountTooltip,
      68             :           child: const Icon(Icons.edit),
      69             :         ),
      70           0 :         FloatingActionButton(
      71             :           heroTag: 'account_view_page_deactivate',
      72           0 :           onPressed: () => ConfirmationWrapper.show(
      73             :             context,
      74           0 :             () => FlowStateMachine.deactivate(nav, store: super.state, uuid: widget.uuid),
      75             :           ),
      76           0 :           tooltip: AppLocale.labels.deleteAccountTooltip,
      77             :           child: const Icon(Icons.delete),
      78             :         ),
      79             :       ]),
      80             :     );
      81             :   }
      82             : 
      83           0 :   String _getTitle(dynamic item) {
      84             :     String prefix = '';
      85           0 :     if (item is InvoiceAppData && item.accountFrom != null) {
      86           0 :       if (item.accountFrom == widget.uuid) {
      87           0 :         final obj = state.getByUuid(item.account) as AccountAppData;
      88           0 :         prefix = "[${AppLocale.labels.transferHeadline} ${AppLocale.labels.to} '${obj.title}'] ";
      89             :       } else {
      90           0 :         final obj = state.getByUuid(item.accountFrom!) as AccountAppData;
      91           0 :         prefix = "[${AppLocale.labels.transferHeadline} ${AppLocale.labels.from} '${obj.title}'] ";
      92             :       }
      93             :     }
      94           0 :     return item != null ? '$prefix${item.title}' : '';
      95             :   }
      96             : 
      97           0 :   String _getRoute(dynamic item) => switch (item.runtimeType) {
      98           0 :         BillAppData => AppRoute.billViewRoute,
      99           0 :         InvoiceAppData => AppRoute.invoiceViewRoute,
     100             :         _ => '',
     101             :       };
     102             : 
     103           0 :   InterfaceIterator<num, dynamic, dynamic> _getSummary() {
     104           0 :     var exchange = Exchange(store: state);
     105           0 :     var account = super.state.getByUuid(widget.uuid) as AccountAppData;
     106           0 :     var bills = state.getStream(AppDataType.bills, filter: (o) => o.account != widget.uuid);
     107           0 :     var inv = state.getStream(AppDataType.invoice, filter: (o) => o.account != widget.uuid || o.accountFrom != null);
     108           0 :     DateTime now = DateTime.now();
     109           0 :     DateTime curr = DateTime(now.year, now.month, 1);
     110           0 :     var data = SplayTreeMap<num, AccountSummaryData>();
     111             :     int increment = 0;
     112           0 :     while (!(bills.isFinished && inv.isFinished)) {
     113           0 :       var boundary = curr.millisecondsSinceEpoch.toDouble();
     114           0 :       var billList = bills.getTill(boundary);
     115           0 :       var invList = inv.getTill(boundary);
     116           0 :       data[increment] = AccountSummaryData(
     117           0 :         title: intl.DateFormat.MMMM().format(curr),
     118           0 :         description: curr.year.toString(),
     119           0 :         currency: account.currency,
     120           0 :         invoices: invList.fold(0.0, (v, e) => v + exchange.reform(e.details ?? 0.0, e.currency, account.currency)),
     121           0 :         bills: billList.fold(0.0, (v, e) => v + exchange.reform(e.details ?? 0.0, e.currency, account.currency)),
     122             :       );
     123           0 :       increment++;
     124           0 :       curr = DateTime(now.year, now.month - increment, 1);
     125             :     }
     126           0 :     return IteratorController(data, transform: (v) => v);
     127             :   }
     128             : 
     129           0 :   Widget buildSummaryWidget(item, BuildContext context) {
     130           0 :     final textTheme = context.textTheme;
     131           0 :     final indent = ThemeHelper.getIndent();
     132           0 :     final alignment = AppDesign.isRightToLeft() ? Alignment.centerLeft : Alignment.centerRight;
     133           0 :     return RowWidget(
     134             :       indent: indent,
     135           0 :       alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     136           0 :       maxWidth: width,
     137           0 :       chunk: [indent, null, null, null, indent],
     138           0 :       children: [
     139             :         const [ThemeHelper.emptyBox],
     140           0 :         [
     141           0 :           Column(
     142           0 :             crossAxisAlignment: AppDesign.getAlignment(),
     143           0 :             children: [
     144           0 :               TextWrapper(
     145           0 :                 item.title,
     146           0 :                 style: textTheme.headlineMedium,
     147             :               ),
     148           0 :               TextWrapper(
     149           0 :                 item.description,
     150           0 :                 style: textTheme.bodySmall,
     151             :               ),
     152             :               ThemeHelper.hIndent
     153             :             ],
     154             :           ),
     155             :         ],
     156           0 :         [
     157           0 :           Align(
     158             :             alignment: alignment,
     159           0 :             child: TextWrapper(
     160           0 :               (item.bills as double).toCurrency(currency: item.currency, withPattern: true),
     161           0 :               style: textTheme.numberMedium,
     162             :             ),
     163             :           ),
     164             :         ],
     165           0 :         [
     166           0 :           Align(
     167             :             alignment: alignment,
     168           0 :             child: TextWrapper(
     169           0 :               (item.invoices as double).toCurrency(currency: item.currency, withPattern: true),
     170           0 :               style: textTheme.numberMedium,
     171             :             ),
     172             :           ),
     173             :         ],
     174             :         const [ThemeHelper.emptyBox],
     175             :       ],
     176             :     );
     177             :   }
     178             : 
     179           0 :   Widget buildLineWidget(item, BuildContext context) {
     180           0 :     return BaseLineWidget(
     181           0 :       uuid: item.uuid ?? '',
     182           0 :       title: _getTitle(item),
     183           0 :       description: item.description ?? '',
     184           0 :       details: item.detailsFormatted,
     185           0 :       progress: item.progress,
     186           0 :       color: item.color ?? Colors.transparent,
     187           0 :       icon: item.icon ?? Icons.radio_button_unchecked_sharp,
     188           0 :       hidden: item.hidden,
     189           0 :       width: width,
     190           0 :       route: _getRoute(item),
     191             :     );
     192             :   }
     193             : 
     194           0 :   @override
     195             :   Widget buildContent(BuildContext context, BoxConstraints constraints) {
     196           0 :     width = ThemeHelper.getWidth(context, 4, constraints);
     197           0 :     bool isLeft = ThemeHelper.isNavRight(context, constraints);
     198             :     if (isLeft) {
     199           0 :       width -= ThemeHelper.barHeight;
     200             :     }
     201           0 :     return Padding(
     202           0 :       padding: EdgeInsets.only(top: ThemeHelper.getIndent()),
     203           0 :       child: Column(
     204           0 :         children: [
     205           0 :           AccountLineWidget(item: state.getByUuid(widget.uuid) as AccountAppData, width: width, count: 1),
     206             :           ThemeHelper.hIndent05,
     207             :           const Divider(height: 2),
     208           0 :           Expanded(
     209           0 :             child: TabWidget(
     210             :               type: TabType.secondary,
     211             :               isLeft: isLeft,
     212           0 :               focus: focus,
     213           0 :               callback: (data) => setState(() => focus = data),
     214           0 :               tabs: [
     215           0 :                 Tab(text: AppLocale.labels.summary),
     216           0 :                 Tab(text: AppLocale.labels.billHeadline),
     217           0 :                 Tab(text: AppLocale.labels.invoiceHeadline),
     218             :               ],
     219           0 :               children: [
     220           0 :                 BaseListInfiniteWidget(
     221           0 :                   stream: _getSummary(),
     222           0 :                   width: width,
     223           0 :                   buildListWidget: buildSummaryWidget,
     224             :                 ),
     225           0 :                 BaseListInfiniteWidget(
     226           0 :                   stream: state.getStream(AppDataType.bills, filter: (o) => o.account != widget.uuid),
     227           0 :                   width: width,
     228           0 :                   buildListWidget: buildLineWidget,
     229             :                 ),
     230           0 :                 BaseListInfiniteWidget(
     231           0 :                   stream: state.getStream(AppDataType.invoice, filter: (o) => o.account != widget.uuid),
     232           0 :                   width: width,
     233           0 :                   buildListWidget: buildLineWidget,
     234             :                 ),
     235             :               ],
     236             :             ),
     237             :           ),
     238             :         ],
     239             :       ),
     240             :     );
     241             :   }
     242             : }

Generated by: LCOV version 1.14