invoice/lib/ui/reports/report_charts.dart

133 lines
4.4 KiB
Dart

// Flutter imports:
import 'package:charts_flutter/flutter.dart';
import 'package:flutter/material.dart';
// Package imports:
import 'package:charts_flutter/flutter.dart' as charts;
// Project imports:
import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen.dart';
import 'package:invoiceninja_flutter/ui/reports/reports_screen_vm.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class ReportCharts extends StatelessWidget {
const ReportCharts({required this.viewModel});
final ReportsScreenVM viewModel;
@override
Widget build(BuildContext context) {
final state = viewModel.state;
final reportState = viewModel.reportState;
final localization = AppLocalization.of(context);
if (reportState.chart.isEmpty || reportState.group.isEmpty) {
return SizedBox();
}
final color = state.prefState.enableDarkMode
? charts.MaterialPalette.white
: charts.MaterialPalette.black;
final numericAxis = charts.NumericAxisSpec(
renderSpec: charts.GridlineRendererSpec(
labelStyle: charts.TextStyleSpec(color: color),
lineStyle: charts.LineStyleSpec(color: color)));
final ordinalAxis = charts.OrdinalAxisSpec(
renderSpec: charts.GridlineRendererSpec(
lineStyle:
charts.LineStyleSpec(color: charts.MaterialPalette.transparent),
labelStyle: charts.TextStyleSpec(fontSize: 10, color: color),
labelRotation: 45,
));
final dateTimeAxis = charts.DateTimeAxisSpec(
renderSpec: charts.SmallTickRendererSpec(
labelStyle: charts.TextStyleSpec(color: color),
lineStyle: charts.LineStyleSpec(color: color),
));
Widget? child;
final columnType = getReportColumnType(reportState.group, context);
switch (columnType) {
case ReportColumnType.string:
case ReportColumnType.bool:
case ReportColumnType.number:
case ReportColumnType.age:
case ReportColumnType.duration:
child = charts.BarChart(
[
charts.Series<dynamic, String?>(
id: 'chart',
colorFn: (dynamic _, __) =>
charts.ColorUtil.fromDartColor(state.accentColor!),
domainFn: (dynamic item, _) =>
columnType == ReportColumnType.age
? localization!.lookup(item['name'])
: item['name'],
measureFn: (dynamic item, _) => item['value'],
data: viewModel.groupTotals.rows!.map((key) {
return {
'name': key,
'value':
viewModel.groupTotals.totals![key]![reportState.chart]
};
}).toList()) as Series<dynamic, String>
],
animate: true,
primaryMeasureAxis: numericAxis,
domainAxis: ordinalAxis,
);
break;
case ReportColumnType.date:
case ReportColumnType.dateTime:
final keys = viewModel.groupTotals.rows!
.where((element) => element!.isNotEmpty)
.toList();
keys.sort((String? str1, String? str2) => str1!.compareTo(str2!));
child = charts.TimeSeriesChart(
[
charts.Series<dynamic, DateTime?>(
id: 'chart',
colorFn: (dynamic _, __) =>
charts.ColorUtil.fromDartColor(state.accentColor!),
domainFn: (dynamic item, _) => DateTime.tryParse(item['name']),
measureFn: (dynamic item, _) => item['value'],
data: keys.map((key) {
return {
'name': key,
'value':
viewModel.groupTotals.totals![key]![reportState.chart]
};
}).toList()) as Series<dynamic, DateTime>
],
animate: true,
primaryMeasureAxis: numericAxis,
domainAxis: dateTimeAxis,
/*
behaviors: [
charts.SeriesLegend(
outsideJustification: charts.OutsideJustification.endDrawArea,
)
],
*/
);
break;
}
return child == null
? SizedBox()
: FormCard(
child: ClipRect(
child: SizedBox(
height: 200,
child: child,
),
),
);
}
}