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/_configs/theme_helper.dart';
8 : import 'package:app_finance/_ext/build_context_ext.dart';
9 : import 'package:app_finance/design/form/simple_input.dart';
10 : import 'package:app_finance/design/wrapper/input_wrapper.dart';
11 : import 'package:app_finance/design/wrapper/row_widget.dart';
12 : import 'package:flutter/material.dart';
13 : import 'package:flutter_currency_picker/flutter_currency_picker.dart';
14 :
15 : class CurrencyExchangeInput extends StatefulWidget {
16 : final Currency? target;
17 : final List<Currency?> source;
18 : final double width;
19 : final double indent;
20 : final ExchangeController controller;
21 :
22 2 : const CurrencyExchangeInput({
23 : super.key,
24 : required this.width,
25 : required this.indent,
26 : required this.target,
27 : required this.controller,
28 : required this.source,
29 : });
30 :
31 2 : @override
32 2 : CurrencyExchangeInputState createState() => CurrencyExchangeInputState();
33 : }
34 :
35 : class CurrencyExchangeInputState extends State<CurrencyExchangeInput> {
36 : Currency? target;
37 : List<Currency?> source = [];
38 :
39 2 : @override
40 : initState() {
41 2 : _update();
42 2 : super.initState();
43 : }
44 :
45 2 : void _update() {
46 6 : target = widget.target;
47 6 : source = widget.source;
48 10 : widget.controller.restate(source, target);
49 : }
50 :
51 8 : String _convert(List<Currency?> val) => val.map((e) => e?.code ?? '-').join('');
52 :
53 2 : @override
54 : Widget build(BuildContext context) {
55 20 : if (target?.code != widget.target?.code || _convert(source) != _convert(widget.source)) {
56 0 : WidgetsBinding.instance.addPostFrameCallback((_) => setState(_update));
57 : return ThemeHelper.emptyBox;
58 : }
59 14 : if (target == null || source.isEmpty || source.where((v) => v != null).isEmpty) {
60 : return ThemeHelper.emptyBox;
61 : }
62 0 : final TextTheme textTheme = context.textTheme;
63 0 : return Column(
64 0 : children: List<Widget>.generate(widget.source.length, (index) {
65 0 : final scope = widget.controller.get(index);
66 0 : if (source[index] == null || scope.from == scope.to) {
67 : return ThemeHelper.emptyBox;
68 : }
69 0 : return Column(
70 0 : mainAxisAlignment: AppDesign.getAlignment<MainAxisAlignment>(),
71 0 : children: [
72 0 : Container(
73 0 : width: widget.width,
74 0 : decoration: BoxDecoration(
75 0 : border: Border.all(color: context.colorScheme.inversePrimary.withOpacity(0.6)),
76 : ),
77 0 : child: Column(
78 0 : mainAxisAlignment: AppDesign.getAlignment<MainAxisAlignment>(),
79 0 : children: [
80 0 : Text(AppLocale.labels.currencyExchange(scope.from, scope.to),
81 0 : style: textTheme.bodyLarge?.copyWith(
82 0 : color: context.colorScheme.primary,
83 : )),
84 0 : Padding(
85 0 : padding: EdgeInsets.fromLTRB(widget.indent, 0, widget.indent, 0),
86 0 : child: RowWidget(
87 0 : indent: widget.indent,
88 0 : maxWidth: widget.width - 2 * widget.indent - 2,
89 : chunk: const [0.5, null],
90 0 : children: [
91 0 : [
92 0 : InputWrapper.text(
93 0 : title: AppLocale.labels.conversion,
94 : controller: scope.rate,
95 0 : tooltip: '${scope.to} ${AppLocale.labels.conversion}',
96 : inputType: const TextInputType.numberWithOptions(decimal: true),
97 0 : formatter: [SimpleInputFormatter.filterDouble],
98 : ),
99 : ],
100 0 : [
101 0 : InputWrapper.text(
102 0 : title: AppLocale.labels.conversionMessage(scope.to),
103 : controller: scope.sum,
104 0 : tooltip: '${scope.from} ${AppLocale.labels.conversionMessage(scope.to)}',
105 : inputType: const TextInputType.numberWithOptions(decimal: true),
106 0 : formatter: [SimpleInputFormatter.filterDouble],
107 : ),
108 : ],
109 : ],
110 : ),
111 : ),
112 : ],
113 : ),
114 : ),
115 0 : SizedBox(height: widget.indent),
116 : ],
117 : );
118 : }),
119 : );
120 : }
121 : }
|