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 'dart:math';
5 :
6 : import 'package:app_finance/_classes/herald/app_design.dart';
7 : import 'package:app_finance/_classes/herald/app_locale.dart';
8 : import 'package:app_finance/_classes/structure/navigation/app_route.dart';
9 : import 'package:app_finance/_ext/build_context_ext.dart';
10 : import 'package:app_finance/charts/bar_vertical_group.dart';
11 : import 'package:app_finance/charts/bar_vertical_single.dart';
12 : import 'package:app_finance/charts/radial_bar_chart.dart';
13 : import 'package:app_finance/_configs/theme_helper.dart';
14 : import 'package:app_finance/design/wrapper/row_widget.dart';
15 : import 'package:app_finance/design/wrapper/tap_widget.dart';
16 : import 'package:flutter/material.dart';
17 :
18 : class BaseGroupWidget extends StatelessWidget {
19 : final String title;
20 : final String description;
21 : final List<dynamic> items;
22 : final List<double> progress;
23 : final List<Color> color;
24 : final double width;
25 : final double total;
26 : final String route;
27 : static const double size = 32;
28 :
29 1 : const BaseGroupWidget({
30 : super.key,
31 : required this.items,
32 : required this.title,
33 : required this.description,
34 : required this.color,
35 : required this.width,
36 : this.progress = const [],
37 : this.route = '',
38 : this.total = 0,
39 : });
40 :
41 1 : Widget buildCategory(BuildContext context, int index, bool toSwap) {
42 2 : final item = items[index];
43 1 : final tooltip = StringBuffer();
44 1 : tooltip.writeAll(
45 9 : ['${AppLocale.labels.title}: "${item.title}"\n', '${AppLocale.labels.details}: ${item.detailsFormatted}']);
46 1 : return TapWidget(
47 1 : tooltip: tooltip.toString(),
48 5 : route: RouteSettings(name: '$route/view', arguments: {routeArguments.uuid: item.uuid}),
49 : child: toSwap
50 0 : ? Column(
51 0 : children: [
52 0 : Icon(item.icon, size: size / 2, color: item.color),
53 : const SizedBox(height: 6.0),
54 0 : BarVerticalSingle(value: item.progress, height: 14.0, color: item.color ?? Colors.transparent),
55 : ],
56 : )
57 1 : : SizedBox(
58 : height: size,
59 : width: size,
60 1 : child: RadialBarChart(
61 1 : color: item.color,
62 1 : icon: item.icon,
63 2 : progress: progress[index],
64 : ),
65 : ),
66 : );
67 : }
68 :
69 1 : @override
70 : Widget build(BuildContext context) {
71 1 : double indent = ThemeHelper.getIndent();
72 1 : final textTheme = context.textTheme;
73 1 : final titleText = Text(
74 1 : title,
75 1 : style: textTheme.headlineMedium,
76 : overflow: TextOverflow.ellipsis,
77 : );
78 1 : final subTitle = Text(
79 1 : description,
80 1 : style: textTheme.bodySmall,
81 : overflow: TextOverflow.ellipsis,
82 : );
83 4 : double titleWidth = [ThemeHelper.getTextWidth(titleText), ThemeHelper.getTextWidth(subTitle)].reduce(max);
84 3 : if (titleWidth > width / 2) {
85 0 : titleWidth = width / 2;
86 : }
87 13 : final toSwap = items.length * size + items.length * indent * 2 > width - titleWidth - indent * 3;
88 :
89 1 : return Column(
90 1 : crossAxisAlignment: AppDesign.getAlignment(),
91 1 : children: [
92 1 : TapWidget(
93 5 : route: RouteSettings(name: '$route/search', arguments: {routeArguments.search: title}),
94 3 : tooltip: AppLocale.labels.search(title),
95 1 : child: RowWidget(
96 : indent: indent,
97 1 : alignment: AppDesign.getAlignment<MainAxisAlignment>(),
98 2 : maxWidth: width + indent,
99 2 : chunk: [indent * 1.5, titleWidth, null],
100 1 : children: [
101 1 : [
102 1 : Padding(
103 1 : padding: EdgeInsets.only(left: indent),
104 4 : child: BarVerticalGroup(value: progress, height: 32.0, width: indent / 2, color: color),
105 : ),
106 : ],
107 1 : [
108 1 : Column(
109 1 : crossAxisAlignment: AppDesign.getAlignment(),
110 1 : children: [titleText, subTitle],
111 : ),
112 : ],
113 1 : [
114 1 : Row(
115 1 : crossAxisAlignment: AppDesign.getInverseAlignment(),
116 1 : mainAxisAlignment: AppDesign.getInverseAlignment<MainAxisAlignment>(),
117 1 : children: List.generate(
118 3 : items.length * 2,
119 1 : (index) {
120 2 : if (index % 2 != 0) {
121 : return ThemeHelper.wIndent;
122 : } else {
123 2 : return buildCategory(context, index ~/ 2, toSwap);
124 : }
125 : },
126 : ),
127 : ),
128 : ]
129 : ],
130 : ),
131 : ),
132 : const Divider(),
133 : ],
134 : );
135 : }
136 : }
|