LCOV - code coverage report
Current view: top level - lib/pages/goal - goal_add_page.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 1 97 1.0 %
Date: 2024-10-04 11:09:33 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_page_state.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:flutter/material.dart';
      19             : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
      20             : 
      21             : class GoalAddPage extends StatefulWidget {
      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           5 :   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 AbstractPageState<GoalAddPage> {
      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             :   bool hasError = false;
      52             : 
      53           0 :   @override
      54             :   void initState() {
      55           0 :     focus = FocusController();
      56           0 :     title = TextEditingController(text: widget.title);
      57           0 :     icon = widget.icon;
      58           0 :     color = widget.color;
      59           0 :     details = TextEditingController(text: widget.details != null ? widget.details.toString() : '');
      60           0 :     final currencyId = AppPreferences.get(AppPreferences.prefCurrency);
      61           0 :     currency = widget.currency ?? CurrencyProvider.find(currencyId);
      62           0 :     closedAt = widget.closedAt;
      63           0 :     super.initState();
      64             :   }
      65             : 
      66           0 :   @override
      67             :   void dispose() {
      68           0 :     focus.dispose();
      69           0 :     title.dispose();
      70           0 :     details.dispose();
      71           0 :     super.dispose();
      72             :   }
      73             : 
      74           0 :   @override
      75           0 :   String getTitle() => AppLocale.labels.createGoalHeader;
      76             : 
      77           0 :   bool hasFormErrors() {
      78           0 :     setState(() => hasError = title.text.isEmpty || closedAt == null);
      79           0 :     return hasError;
      80             :   }
      81             : 
      82           0 :   void updateStorage() {
      83           0 :     if (currency != null) {
      84           0 :       CurrencyProvider.pin(currency!);
      85             :     }
      86           0 :     state.add(GoalAppData(
      87           0 :       title: title.text,
      88           0 :       initial: Exchange(store: state).reform(state.getTotal(AppDataType.accounts), Exchange.defaultCurrency, currency),
      89             :       progress: 0.0,
      90           0 :       color: color,
      91             :       hidden: false,
      92           0 :       currency: currency,
      93           0 :       icon: icon,
      94           0 :       details: double.tryParse(details.text) ?? 0.0,
      95           0 :       closedAt: closedAt,
      96             :     ));
      97             :   }
      98             : 
      99           0 :   @override
     100           0 :   String getButtonName() => AppLocale.labels.createGoalTooltip;
     101             : 
     102           0 :   @override
     103             :   Widget buildButton(BuildContext context, BoxConstraints constraints) {
     104           0 :     NavigatorState nav = Navigator.of(context);
     105           0 :     return FullSizedButtonWidget(
     106             :       constraints: constraints,
     107           0 :       controller: focus,
     108           0 :       onPressed: () => {
     109           0 :         setState(() {
     110           0 :           if (hasFormErrors()) {
     111             :             return;
     112             :           }
     113           0 :           updateStorage();
     114           0 :           nav.pop();
     115             :         })
     116             :       },
     117           0 :       title: getButtonName(),
     118             :       icon: Icons.save,
     119             :     );
     120             :   }
     121             : 
     122           0 :   @override
     123             :   Widget buildContent(BuildContext context, BoxConstraints constraints) {
     124           0 :     double indent = ThemeHelper.getIndent(2);
     125           0 :     double width = ThemeHelper.getWidth(context, 6, constraints);
     126             : 
     127           0 :     return SingleScrollWrapper(
     128           0 :       controller: focus,
     129           0 :       child: Container(
     130           0 :         margin: EdgeInsets.fromLTRB(indent, indent, indent, 240),
     131           0 :         child: Column(
     132           0 :           crossAxisAlignment: AppDesign.getAlignment(),
     133           0 :           children: [
     134           0 :             InputWrapper.text(
     135           0 :               title: AppLocale.labels.titleGoal,
     136           0 :               showError: hasError && title.text.isEmpty,
     137           0 :               controller: title,
     138             :               isRequired: true,
     139           0 :               tooltip: AppLocale.labels.titleGoalTooltip,
     140             :             ),
     141           0 :             RowWidget(
     142             :               indent: indent,
     143           0 :               maxWidth: width + indent,
     144           0 :               alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     145             :               chunk: const [null, null],
     146           0 :               children: [
     147           0 :                 [
     148           0 :                   InputWrapper.icon(
     149           0 :                     title: AppLocale.labels.icon,
     150           0 :                     value: icon,
     151           0 :                     onChange: (value) => setState(() => icon = value),
     152             :                   ),
     153             :                 ],
     154           0 :                 [
     155           0 :                   InputWrapper.color(
     156           0 :                     title: AppLocale.labels.color,
     157           0 :                     value: color,
     158           0 :                     onChange: (value) => setState(() => color = value),
     159             :                   ),
     160             :                 ],
     161             :               ],
     162             :             ),
     163           0 :             RowWidget(
     164             :               indent: indent,
     165           0 :               maxWidth: width + indent,
     166           0 :               alignment: AppDesign.getAlignment<MainAxisAlignment>(),
     167             :               chunk: const [90, null],
     168           0 :               children: [
     169           0 :                 [
     170           0 :                   InputWrapper.currency(
     171           0 :                     title: AppLocale.labels.currency,
     172             :                     type: NamedInputType.currencyShort,
     173           0 :                     value: currency,
     174           0 :                     tooltip: AppLocale.labels.currencyTooltip,
     175           0 :                     onChange: (value) => setState(() => currency = value),
     176             :                   ),
     177             :                 ],
     178           0 :                 [
     179           0 :                   InputWrapper.text(
     180           0 :                     title: AppLocale.labels.targetAmount,
     181           0 :                     controller: details,
     182             :                     inputType: const TextInputType.numberWithOptions(decimal: true),
     183           0 :                     tooltip: AppLocale.labels.billSetTooltip,
     184           0 :                     formatter: [
     185           0 :                       SimpleInputFormatter.filterDouble,
     186             :                     ],
     187             :                   ),
     188             :                 ],
     189             :               ],
     190             :             ),
     191           0 :             InputWrapper(
     192           0 :               title: AppLocale.labels.closedAt,
     193             :               type: NamedInputType.dateSelector,
     194           0 :               showError: hasError && closedAt == null,
     195           0 :               value: closedAt,
     196           0 :               onChange: (value) => setState(() => closedAt = value),
     197             :             ),
     198             :           ],
     199             :         ),
     200             :       ),
     201             :     );
     202             :   }
     203             : }

Generated by: LCOV version 1.14