131 lines
4.3 KiB
Dart
131 lines
4.3 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())
|
|
],
|
|
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 FormCard(
|
|
child: ClipRect(
|
|
child: SizedBox(
|
|
height: 200,
|
|
child: child,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|