Dashboard

This commit is contained in:
Hillel Coren 2018-11-12 12:04:10 +02:00
parent 2633a2e1a1
commit 0f9355f17e
3 changed files with 80 additions and 58 deletions

View File

@ -4,6 +4,15 @@ import 'package:memoize/memoize.dart';
import 'package:built_collection/built_collection.dart'; import 'package:built_collection/built_collection.dart';
import 'package:invoiceninja_flutter/data/models/models.dart'; import 'package:invoiceninja_flutter/data/models/models.dart';
class ChartDataGroup {
ChartDataGroup(this.name);
final String name;
final List<ChartMoneyData> rawSeries = [];
dynamic chartSeries;
double total = 0.0;
}
class ChartMoneyData { class ChartMoneyData {
ChartMoneyData(this.date, this.amount); ChartMoneyData(this.date, this.amount);
@ -32,14 +41,17 @@ var memoizedChartOutstandingQuotes = memo4((CompanyEntity company,
clientMap: clientMap, clientMap: clientMap,
isQuote: true)); isQuote: true));
List<ChartMoneyData> chartOutstandingInvoices({ List<ChartDataGroup> chartOutstandingInvoices({
CompanyEntity company, CompanyEntity company,
DashboardUIState settings, DashboardUIState settings,
BuiltMap<int, InvoiceEntity> invoiceMap, BuiltMap<int, InvoiceEntity> invoiceMap,
BuiltMap<int, ClientEntity> clientMap, BuiltMap<int, ClientEntity> clientMap,
bool isQuote = false, bool isQuote = false,
}) { }) {
final Map<String, double> totals = {}; final Map<String, Map<String, double>> totals = {};
const STATUS_ACTIVE = 'active';
const STATUS_OUTSTANDING = 'outstanding';
invoiceMap.forEach((int, invoice) { invoiceMap.forEach((int, invoice) {
final client = final client =
@ -61,26 +73,41 @@ List<ChartMoneyData> chartOutstandingInvoices({
// skip it // skip it
} else { } else {
if (totals[invoice.invoiceDate] == null) { if (totals[invoice.invoiceDate] == null) {
totals[invoice.invoiceDate] = 0.0; totals[STATUS_ACTIVE][invoice.invoiceDate] = 0.0;
totals[STATUS_OUTSTANDING][invoice.invoiceDate] = 0.0;
} }
totals[invoice.invoiceDate] += invoice.amount;
totals[STATUS_ACTIVE][invoice.invoiceDate] += invoice.amount;
totals[STATUS_OUTSTANDING][invoice.invoiceDate] += invoice.balance;
} }
}); });
final List<ChartMoneyData> data = []; final ChartDataGroup activeData = ChartDataGroup(STATUS_ACTIVE);
final ChartDataGroup outstandingData = ChartDataGroup(STATUS_OUTSTANDING);
var date = DateTime.parse(settings.startDate(company)); var date = DateTime.parse(settings.startDate(company));
final endDate = DateTime.parse(settings.endDate(company)); final endDate = DateTime.parse(settings.endDate(company));
while (!date.isAfter(endDate)) { while (!date.isAfter(endDate)) {
final key = convertDateTimeToSqlDate(date); final key = convertDateTimeToSqlDate(date);
if (totals.containsKey(key)) { if (totals[STATUS_ACTIVE].containsKey(key)) {
data.add(ChartMoneyData(date, totals[key])); activeData.rawSeries.add(ChartMoneyData(date, totals[STATUS_ACTIVE][key]));
activeData.total += totals[STATUS_ACTIVE][key];
outstandingData.rawSeries
.add(ChartMoneyData(date, totals[STATUS_OUTSTANDING][key]));
outstandingData.total += totals[STATUS_OUTSTANDING][key];
} else { } else {
data.add(ChartMoneyData(date, 0.0)); activeData.rawSeries.add(ChartMoneyData(date, 0.0));
outstandingData.rawSeries.add(ChartMoneyData(date, 0.0));
} }
date = date.add(Duration(days: 1)); date = date.add(Duration(days: 1));
} }
final List<ChartDataGroup> data = [
activeData,
outstandingData,
];
return data; return data;
} }

View File

@ -1,21 +1,18 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart'; import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart'; import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/redux/dashboard/dashboard_selectors.dart';
import 'package:invoiceninja_flutter/ui/app/form_card.dart'; import 'package:invoiceninja_flutter/ui/app/form_card.dart';
import 'package:charts_flutter/flutter.dart' as charts; import 'package:charts_flutter/flutter.dart' as charts;
import 'package:invoiceninja_flutter/utils/formatting.dart'; import 'package:invoiceninja_flutter/utils/formatting.dart';
class DashboardChart extends StatefulWidget { class DashboardChart extends StatefulWidget {
const DashboardChart( const DashboardChart(
{this.series, {this.data,
this.amount,
this.previousAmount,
this.title, this.title,
this.currencyId}); this.currencyId});
final List<charts.Series> series; final List<ChartDataGroup> data;
final double previousAmount;
final double amount;
final String title; final String title;
final int currencyId; final int currencyId;
@ -66,6 +63,7 @@ class _DashboardChartState extends State<DashboardChart> {
? charts.MaterialPalette.white ? charts.MaterialPalette.white
: charts.MaterialPalette.gray.shade700; : charts.MaterialPalette.gray.shade700;
/*
final chart = charts.TimeSeriesChart( final chart = charts.TimeSeriesChart(
widget.series, widget.series,
animate: true, animate: true,
@ -109,6 +107,7 @@ class _DashboardChartState extends State<DashboardChart> {
final String changeString = widget.amount == 0 || widget.previousAmount == 0 final String changeString = widget.amount == 0 || widget.previousAmount == 0
? '' ? ''
: '$changeAmount ($changePercent)'; : '$changeAmount ($changePercent)';
*/
return FormCard( return FormCard(
children: <Widget>[ children: <Widget>[
@ -116,6 +115,7 @@ class _DashboardChartState extends State<DashboardChart> {
padding: EdgeInsets.symmetric(vertical: 14.0, horizontal: 4.0), padding: EdgeInsets.symmetric(vertical: 14.0, horizontal: 4.0),
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
Text(widget.title,),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
@ -125,6 +125,7 @@ class _DashboardChartState extends State<DashboardChart> {
children: <Widget>[ children: <Widget>[
Text(widget.title, Text(widget.title,
style: Theme.of(context).textTheme.subhead), style: Theme.of(context).textTheme.subhead),
/*
Text( Text(
formatNumber(widget.amount, context, formatNumber(widget.amount, context,
currencyId: widget.currencyId), currencyId: widget.currencyId),
@ -138,6 +139,7 @@ class _DashboardChartState extends State<DashboardChart> {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
*/
], ],
), ),
), ),
@ -158,7 +160,7 @@ class _DashboardChartState extends State<DashboardChart> {
height: 200.0, height: 200.0,
child: Padding( child: Padding(
padding: const EdgeInsets.only(top: 10.0), padding: const EdgeInsets.only(top: 10.0),
child: chart, //child: chart,
), ),
), ),
], ],

View File

@ -112,8 +112,8 @@ class DashboardPanels extends StatelessWidget {
final data = memoizedChartOutstandingInvoices(state.selectedCompany, final data = memoizedChartOutstandingInvoices(state.selectedCompany,
settings, state.invoiceState.map, state.clientState.map); settings, state.invoiceState.map, state.clientState.map);
final series = [ data.forEach((dataGroup) {
charts.Series<ChartMoneyData, DateTime>( dataGroup.chartSeries = charts.Series<ChartMoneyData, DateTime>(
domainFn: (ChartMoneyData chartData, _) => chartData.date, domainFn: (ChartMoneyData chartData, _) => chartData.date,
measureFn: (ChartMoneyData chartData, _) => chartData.amount, measureFn: (ChartMoneyData chartData, _) => chartData.amount,
colorFn: (ChartMoneyData chartData, _) => colorFn: (ChartMoneyData chartData, _) =>
@ -122,15 +122,8 @@ class DashboardPanels extends StatelessWidget {
displayName: settings.enableComparison displayName: settings.enableComparison
? localization.current ? localization.current
: localization.invoices, : localization.invoices,
data: data, data: dataGroup.rawSeries,
), );
];
double total = 0.0;
double previousTotal = 0.0;
data.forEach((dynamic item) {
total += item.amount;
});
if (settings.enableComparison) { if (settings.enableComparison) {
final offsetData = memoizedChartOutstandingInvoices( final offsetData = memoizedChartOutstandingInvoices(
@ -140,11 +133,14 @@ class DashboardPanels extends StatelessWidget {
state.clientState.map); state.clientState.map);
final List<ChartMoneyData> previousData = []; final List<ChartMoneyData> previousData = [];
for (int i = 0; i < min(data.length, offsetData.length); i++) { for (int i = 0;
previousData.add(ChartMoneyData(data[i].date, offsetData[i].amount)); i < min(dataGroup.rawSeries.length, offsetData.length);
i++) {
previousData.add(ChartMoneyData(dataGroup.rawSeries[i].date,
offsetData[data.indexOf(dataGroup)].rawSeries[i].amount));
} }
series.add( dataGroup.chartSeries.add(
charts.Series<ChartMoneyData, DateTime>( charts.Series<ChartMoneyData, DateTime>(
domainFn: (ChartMoneyData chartData, _) => chartData.date, domainFn: (ChartMoneyData chartData, _) => chartData.date,
measureFn: (ChartMoneyData chartData, _) => chartData.amount, measureFn: (ChartMoneyData chartData, _) => chartData.amount,
@ -155,16 +151,11 @@ class DashboardPanels extends StatelessWidget {
data: previousData, data: previousData,
), ),
); );
previousData.forEach((dynamic item) {
previousTotal += item.amount;
});
} }
});
return DashboardChart( return DashboardChart(
series: series, data: data,
amount: total,
previousAmount: previousTotal,
title: localization.invoices, title: localization.invoices,
currencyId: settings.currencyId > 0 currencyId: settings.currencyId > 0
? settings.currencyId ? settings.currencyId
@ -172,6 +163,7 @@ class DashboardPanels extends StatelessWidget {
); );
} }
/*
Widget _paymentChart(BuildContext context) { Widget _paymentChart(BuildContext context) {
if (!viewModel.state.paymentState.isLoaded) { if (!viewModel.state.paymentState.isLoaded) {
return LoadingIndicator(useCard: true); return LoadingIndicator(useCard: true);
@ -324,6 +316,7 @@ class DashboardPanels extends StatelessWidget {
: state.selectedCompany.currencyId, : state.selectedCompany.currencyId,
); );
} }
*/
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -335,8 +328,8 @@ class DashboardPanels extends StatelessWidget {
height: 74.0, height: 74.0,
), ),
_invoiceChart(context), _invoiceChart(context),
_paymentChart(context), //_paymentChart(context),
_quoteChart(context), //_quoteChart(context),
], ],
), ),
ConstrainedBox( ConstrainedBox(