LCOV - code coverage report
Current view: top level - lib/pages/bill/widgets - transfer_tab.dart Coverage Total Hit
Test: lcov.info Lines: 0.9 % 114 1
Test Date: 2026-11-14 15:08:11 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 'package:app_finance/_classes/controller/exchange_controller.dart';
       5              : import 'package:app_finance/_classes/herald/app_design.dart';
       6              : import 'package:app_finance/_classes/herald/app_locale.dart';
       7              : import 'package:app_finance/_classes/structure/currency/exchange.dart';
       8              : import 'package:app_finance/_classes/structure/invoice_app_data.dart';
       9              : import 'package:app_finance/_classes/controller/focus_controller.dart';
      10              : import 'package:app_finance/_classes/storage/app_data.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/wrapper/input_wrapper.dart';
      14              : import 'package:app_finance/pages/_interfaces/interface_page_inject.dart';
      15              : import 'package:app_finance/design/form/currency_exchange_input.dart';
      16              : import 'package:app_finance/design/form/date_time_input.dart';
      17              : import 'package:app_finance/design/button/full_sized_button_widget.dart';
      18              : import 'package:app_finance/design/wrapper/row_widget.dart';
      19              : import 'package:app_finance/design/form/simple_input.dart';
      20              : import 'package:app_finance/design/wrapper/single_scroll_wrapper.dart';
      21              : import 'package:material_ui/material_ui.dart';
      22              : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
      23              : 
      24              : class TransferTab<T> extends StatefulWidget {
      25              :   final String? accountFrom;
      26              :   final String? accountTo;
      27              :   final double? amount;
      28              :   final String? description;
      29              :   final Currency? currency;
      30              :   final DateTime? createdAt;
      31              :   final AppData state;
      32              :   final bool isLeft;
      33              :   final FnPageCallback callback;
      34              : 
      35            1 :   const TransferTab({
      36              :     super.key,
      37              :     required this.state,
      38              :     required this.callback,
      39              :     this.accountFrom,
      40              :     this.accountTo,
      41              :     this.amount,
      42              :     this.description,
      43              :     this.currency,
      44              :     this.createdAt,
      45              :     this.isLeft = false,
      46              :   });
      47              : 
      48            0 :   @override
      49            0 :   TransferTabState createState() => TransferTabState();
      50              : }
      51              : 
      52              : class TransferTabState<T extends TransferTab> extends State<T> {
      53              :   late FocusController focus;
      54              :   String? accountFrom;
      55              :   String? accountTo;
      56              :   Currency? accountFromCurrency;
      57              :   Currency? accountToCurrency;
      58              :   late TextEditingController amount;
      59              :   late TextEditingController description;
      60              :   late ExchangeController exchange;
      61              :   late DateTime createdAt;
      62              :   Currency? currency;
      63              :   bool hasErrors = false;
      64              :   bool isPushed = false;
      65              : 
      66            0 :   @override
      67              :   void initState() {
      68            0 :     focus = FocusController();
      69            0 :     accountFrom = widget.accountFrom;
      70            0 :     accountTo = widget.accountTo;
      71            0 :     createdAt = widget.createdAt ?? DateTime.now();
      72            0 :     amount = TextEditingController(text: widget.amount != null ? widget.amount.toString() : '');
      73            0 :     description = TextEditingController(text: widget.description);
      74            0 :     currency = widget.currency ?? Exchange.defaultCurrency;
      75            0 :     exchange = ExchangeController({}, store: widget.state, targetController: amount, target: currency, source: []);
      76              : 
      77            0 :     widget.callback((
      78            0 :       buildButton: buildButton,
      79            0 :       buttonName: getButtonName(),
      80            0 :       title: getTitle(),
      81              :     ));
      82            0 :     super.initState();
      83              :   }
      84              : 
      85            0 :   @override
      86              :   dispose() {
      87            0 :     isPushed = false;
      88            0 :     amount.dispose();
      89            0 :     description.dispose();
      90            0 :     exchange.dispose();
      91            0 :     focus.dispose();
      92            0 :     super.dispose();
      93              :   }
      94              : 
      95            0 :   bool hasFormErrors() {
      96            0 :     setState(() => hasErrors = accountFrom == null || accountTo == null);
      97            0 :     return hasErrors;
      98              :   }
      99              : 
     100            0 :   String getTitle() => AppLocale.labels.createBillHeader;
     101              : 
     102            0 :   void updateStorage() {
     103            0 :     exchange.save();
     104            0 :     widget.state.add(getValues());
     105              :   }
     106              : 
     107            0 :   InvoiceAppData getValues() => InvoiceAppData(
     108            0 :         title: description.text,
     109            0 :         color: widget.state.getByUuid(accountFrom ?? '')?.color,
     110            0 :         account: accountTo ?? '',
     111            0 :         accountFrom: accountFrom ?? '',
     112            0 :         details: double.tryParse(amount.text) ?? 0.0,
     113            0 :         currency: currency,
     114            0 :         createdAt: createdAt,
     115              :       );
     116              : 
     117            0 :   String getButtonName() => AppLocale.labels.createTransferTooltip;
     118              : 
     119            0 :   Widget buildButton(BuildContext context, BoxConstraints constraints) {
     120            0 :     final nav = Navigator.of(context);
     121            0 :     return FullSizedButtonWidget(
     122              :       constraints: constraints,
     123            0 :       controller: focus,
     124            0 :       onPressed: () => {
     125            0 :         setState(() {
     126            0 :           if (hasFormErrors()) {
     127              :             return;
     128              :           }
     129            0 :           updateStorage();
     130            0 :           nav.pop();
     131              :         })
     132              :       },
     133            0 :       title: getButtonName(),
     134              :       icon: Icons.save,
     135              :     );
     136              :   }
     137              : 
     138            0 :   @override
     139              :   Widget build(BuildContext context) {
     140            0 :     final textTheme = context.textTheme;
     141            0 :     final indent = ThemeHelper.getIndent(2);
     142            0 :     return SingleScrollWrapper(
     143            0 :       controller: focus,
     144            0 :       child: Container(
     145            0 :         margin: EdgeInsets.fromLTRB(indent, indent, indent, 240),
     146            0 :         child: LayoutBuilder(builder: (context, constraints) {
     147            0 :           double width = constraints.maxWidth;
     148            0 :           return Column(
     149            0 :             crossAxisAlignment: AppDesign.getAlignment(),
     150            0 :             children: [
     151            0 :               InputWrapper(
     152              :                 type: NamedInputType.accountSelector,
     153              :                 isRequired: true,
     154            0 :                 value: accountFrom != null ? widget.state.getByUuid(accountFrom!) : null,
     155            0 :                 title: AppLocale.labels.accountFrom,
     156            0 :                 tooltip: '${AppLocale.labels.titleAccountTooltip} (${AppLocale.labels.accountFrom})',
     157            0 :                 showError: hasErrors && accountFrom == null,
     158            0 :                 state: widget.state,
     159            0 :                 onChange: (value) => setState(() {
     160            0 :                   accountFrom = value?.uuid;
     161              :                   if (value != null) {
     162            0 :                     accountFromCurrency = value.currency;
     163            0 :                     currency = accountFromCurrency;
     164              :                   }
     165              :                 }),
     166              :                 width: width,
     167              :               ),
     168            0 :               InputWrapper(
     169              :                 type: NamedInputType.accountSelector,
     170              :                 isRequired: true,
     171            0 :                 value: accountTo != null ? widget.state.getByUuid(accountTo!) : null,
     172            0 :                 title: AppLocale.labels.accountTo,
     173            0 :                 tooltip: '${AppLocale.labels.titleAccountTooltip} (${AppLocale.labels.accountTo})',
     174            0 :                 showError: hasErrors && accountTo == null,
     175            0 :                 state: widget.state,
     176            0 :                 onChange: (value) => setState(() {
     177            0 :                   accountTo = value?.uuid;
     178              :                   if (value != null) {
     179            0 :                     accountToCurrency = value.currency;
     180            0 :                     currency ??= accountToCurrency;
     181              :                   }
     182              :                 }),
     183              :                 width: width,
     184              :               ),
     185            0 :               RowWidget(
     186              :                 indent: indent,
     187              :                 maxWidth: width,
     188              :                 chunk: const [125, null],
     189            0 :                 children: [
     190            0 :                   [
     191            0 :                     InputWrapper.currency(
     192              :                       type: NamedInputType.currencyShort,
     193            0 :                       value: currency,
     194            0 :                       title: AppLocale.labels.currency,
     195            0 :                       tooltip: AppLocale.labels.currencyTooltip,
     196            0 :                       onChange: (value) => setState(() => currency = value),
     197              :                     ),
     198              :                   ],
     199            0 :                   [
     200            0 :                     InputWrapper.text(
     201            0 :                       title: AppLocale.labels.expenseTransfer,
     202            0 :                       tooltip: AppLocale.labels.billSetTooltip,
     203            0 :                       controller: amount,
     204              :                       inputType: const TextInputType.numberWithOptions(decimal: true),
     205            0 :                       formatter: [
     206            0 :                         SimpleInputFormatter.filterDouble,
     207              :                       ],
     208              :                     ),
     209              :                   ],
     210              :                 ],
     211              :               ),
     212            0 :               CurrencyExchangeInput(
     213            0 :                 key: ValueKey('transfer${currency?.code}${accountFromCurrency?.code}${accountToCurrency?.code}'),
     214            0 :                 width: width + indent,
     215              :                 indent: indent,
     216            0 :                 target: currency,
     217            0 :                 controller: exchange,
     218            0 :                 source: [accountFromCurrency, accountToCurrency, Exchange.defaultCurrency],
     219              :               ),
     220            0 :               InputWrapper.text(
     221            0 :                 title: AppLocale.labels.description,
     222            0 :                 tooltip: AppLocale.labels.transferTooltip,
     223            0 :                 controller: description,
     224              :               ),
     225            0 :               Text(
     226            0 :                 AppLocale.labels.balanceDate,
     227            0 :                 style: textTheme.bodyLarge,
     228              :               ),
     229            0 :               DateTimeInput(
     230            0 :                 width: width - indent,
     231            0 :                 value: createdAt,
     232            0 :                 setState: (value) => setState(() => createdAt = value),
     233              :               ),
     234              :               ThemeHelper.formEndBox,
     235              :             ],
     236              :           );
     237              :         }),
     238              :       ),
     239              :     );
     240              :   }
     241              : }
        

Generated by: LCOV version 2.0-1