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

Generated by: LCOV version 2.0-1