LCOV - code coverage report
Current view: top level - lib/pages/goal - goal_add_page.dart Coverage Total Hit
Test: lcov.info Lines: 1.1 % 93 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/herald/app_design.dart';
       5              : import 'package:app_finance/_classes/herald/app_locale.dart';
       6              : import 'package:app_finance/_classes/structure/currency/exchange.dart';
       7              : import 'package:app_finance/_classes/structure/goal_app_data.dart';
       8              : import 'package:app_finance/_classes/controller/focus_controller.dart';
       9              : import 'package:app_finance/_classes/storage/app_data.dart';
      10              : import 'package:app_finance/_configs/theme_helper.dart';
      11              : import 'package:app_finance/_classes/storage/app_preferences.dart';
      12              : import 'package:app_finance/design/wrapper/input_wrapper.dart';
      13              : import 'package:app_finance/pages/_interfaces/abstract_add_page.dart';
      14              : import 'package:app_finance/design/button/full_sized_button_widget.dart';
      15              : import 'package:app_finance/design/form/simple_input.dart';
      16              : import 'package:app_finance/design/wrapper/row_widget.dart';
      17              : import 'package:app_finance/design/wrapper/single_scroll_wrapper.dart';
      18              : import 'package:material_ui/material_ui.dart';
      19              : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
      20              : 
      21              : class GoalAddPage extends AbstractAddPage {
      22              :   final String? title;
      23              :   final IconData? icon;
      24              :   final MaterialColor? color;
      25              :   final Currency? currency;
      26              :   final double? details;
      27              :   final DateTime? closedAt;
      28              : 
      29            2 :   const GoalAddPage({
      30              :     super.key,
      31              :     this.title,
      32              :     this.icon,
      33              :     this.color,
      34              :     this.currency,
      35              :     this.details,
      36              :     this.closedAt,
      37              :   });
      38              : 
      39            0 :   @override
      40            0 :   GoalAddPageState createState() => GoalAddPageState();
      41              : }
      42              : 
      43              : class GoalAddPageState<T extends GoalAddPage> extends AbstractAddPageState<T> {
      44              :   late FocusController focus;
      45              :   late TextEditingController title;
      46              :   late TextEditingController details;
      47              :   IconData? icon;
      48              :   MaterialColor? color;
      49              :   Currency? currency;
      50              :   DateTime? closedAt;
      51              : 
      52            0 :   @override
      53              :   void initState() {
      54            0 :     focus = FocusController();
      55            0 :     title = TextEditingController(text: widget.title);
      56            0 :     icon = widget.icon;
      57            0 :     color = widget.color;
      58            0 :     details = TextEditingController(text: widget.details != null ? widget.details.toString() : '');
      59            0 :     final currencyId = AppPreferences.get(AppPreferences.prefCurrency);
      60            0 :     currency = widget.currency ?? CurrencyProvider.find(currencyId);
      61            0 :     closedAt = widget.closedAt;
      62            0 :     super.initState();
      63              :   }
      64              : 
      65            0 :   @override
      66              :   void dispose() {
      67            0 :     focus.dispose();
      68            0 :     title.dispose();
      69            0 :     details.dispose();
      70            0 :     super.dispose();
      71              :   }
      72              : 
      73            0 :   @override
      74            0 :   String getTitle() => AppLocale.labels.createGoalHeader;
      75              : 
      76            0 :   @override
      77              :   bool hasFormErrors() {
      78            0 :     setState(() => hasError = title.text.isEmpty || closedAt == null);
      79            0 :     return hasError;
      80              :   }
      81              : 
      82            0 :   @override
      83              :   void updateStorage() {
      84            0 :     if (currency != null) {
      85            0 :       CurrencyProvider.pin(currency!);
      86              :     }
      87            0 :     state.add(GoalAppData(
      88            0 :       title: title.text,
      89            0 :       initial: Exchange(store: state).reform(state.getTotal(AppDataType.accounts), Exchange.defaultCurrency, currency),
      90              :       progress: 0.0,
      91            0 :       color: color,
      92              :       hidden: false,
      93            0 :       currency: currency,
      94            0 :       icon: icon,
      95            0 :       details: double.tryParse(details.text) ?? 0.0,
      96            0 :       closedAt: closedAt,
      97              :     ));
      98              :   }
      99              : 
     100            0 :   @override
     101            0 :   String getButtonName() => AppLocale.labels.createGoalTooltip;
     102              : 
     103            0 :   @override
     104              :   Widget buildButton(BuildContext context, BoxConstraints constraints) {
     105            0 :     NavigatorState nav = Navigator.of(context);
     106            0 :     return FullSizedButtonWidget(
     107              :       constraints: constraints,
     108            0 :       controller: focus,
     109            0 :       onPressed: () => triggerActionButton(nav),
     110            0 :       title: getButtonName(),
     111              :       icon: Icons.save,
     112              :     );
     113              :   }
     114              : 
     115            0 :   @override
     116              :   Widget buildContent(BuildContext context, BoxConstraints constraints) {
     117            0 :     double indent = ThemeHelper.getIndent(2);
     118            0 :     double width = ThemeHelper.getWidth(context, 6, constraints);
     119              : 
     120            0 :     return SingleScrollWrapper(
     121            0 :       controller: focus,
     122            0 :       child: Container(
     123            0 :         margin: EdgeInsets.fromLTRB(indent, indent, indent, 240),
     124            0 :         child: Column(
     125            0 :           crossAxisAlignment: AppDesign.getAlignment(),
     126            0 :           children: [
     127            0 :             InputWrapper.text(
     128            0 :               title: AppLocale.labels.titleGoal,
     129            0 :               showError: hasError && title.text.isEmpty,
     130            0 :               controller: title,
     131              :               isRequired: true,
     132            0 :               tooltip: AppLocale.labels.titleGoalTooltip,
     133              :             ),
     134            0 :             RowWidget(
     135              :               indent: indent,
     136            0 :               maxWidth: width + indent,
     137            0 :               alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     138              :               chunk: const [null, null],
     139            0 :               children: [
     140            0 :                 [
     141            0 :                   InputWrapper.icon(
     142            0 :                     title: AppLocale.labels.icon,
     143            0 :                     value: icon,
     144            0 :                     onChange: (value) => setState(() => icon = value),
     145              :                   ),
     146              :                 ],
     147            0 :                 [
     148            0 :                   InputWrapper.color(
     149            0 :                     title: AppLocale.labels.color,
     150            0 :                     value: color,
     151            0 :                     onChange: (value) => setState(() => color = value),
     152              :                   ),
     153              :                 ],
     154              :               ],
     155              :             ),
     156            0 :             RowWidget(
     157              :               indent: indent,
     158            0 :               maxWidth: width + indent,
     159            0 :               alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     160              :               chunk: const [100, null],
     161            0 :               children: [
     162            0 :                 [
     163            0 :                   InputWrapper.currency(
     164            0 :                     title: AppLocale.labels.currency,
     165              :                     type: NamedInputType.currencyShort,
     166            0 :                     value: currency,
     167            0 :                     tooltip: AppLocale.labels.currencyTooltip,
     168            0 :                     onChange: (value) => setState(() => currency = value),
     169              :                   ),
     170              :                 ],
     171            0 :                 [
     172            0 :                   InputWrapper.text(
     173            0 :                     title: AppLocale.labels.targetAmount,
     174            0 :                     controller: details,
     175              :                     inputType: const TextInputType.numberWithOptions(decimal: true),
     176            0 :                     tooltip: AppLocale.labels.billSetTooltip,
     177            0 :                     formatter: [
     178            0 :                       SimpleInputFormatter.filterDouble,
     179              :                     ],
     180              :                   ),
     181              :                 ],
     182              :               ],
     183              :             ),
     184            0 :             InputWrapper(
     185            0 :               title: AppLocale.labels.closedAt,
     186              :               type: NamedInputType.dateSelector,
     187            0 :               showError: hasError && closedAt == null,
     188            0 :               value: closedAt,
     189            0 :               onChange: (value) => setState(() => closedAt = value),
     190              :             ),
     191              :           ],
     192              :         ),
     193              :       ),
     194              :     );
     195              :   }
     196              : }
        

Generated by: LCOV version 2.0-1