diff --git a/android/build.gradle b/android/build.gradle index c6c43cd6941..ae90d44bb9e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '1.9.10' repositories { google() mavenCentral() @@ -22,11 +22,9 @@ allprojects { rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { project.evaluationDependsOn(':app') } -tasks.register("clean", Delete) { +task clean(type: Delete) { delete rootProject.buildDir } diff --git a/android/build.gradle.foss b/android/build.gradle.foss index 14f26a05cf1..0889573ccc7 100644 --- a/android/build.gradle.foss +++ b/android/build.gradle.foss @@ -1,5 +1,5 @@ buildscript { - ext.kotlin_version = '1.7.22' + ext.kotlin_version = '1.9.10' repositories { google() mavenCentral() diff --git a/lib/redux/dashboard/dashboard_state.dart b/lib/redux/dashboard/dashboard_state.dart index 6c851c20a53..1bfb281951d 100644 --- a/lib/redux/dashboard/dashboard_state.dart +++ b/lib/redux/dashboard/dashboard_state.dart @@ -68,6 +68,8 @@ abstract class DashboardUISettings static const String FIELD_ACTIVE_QUOTES = 'total_active_quotes'; static const String FIELD_APPROVED_QUOTES = 'total_approved_quotes'; static const String FIELD_UNAPPROVED_QUOTES = 'total_unapproved_quotes'; + static const String FIELD_INVOICED_QUOTES = 'total_invoiced_quotes'; + static const String FIELD_INVOICE_PAID_QUOTES = 'total_invoice_paid_quotes'; static const String FIELD_LOGGED_TASKS = 'total_logged_tasks'; static const String FIELD_INVOICED_TASKS = 'total_invoiced_tasks'; static const String FIELD_PAID_TASKS = 'total_paid_tasks'; diff --git a/lib/ui/dashboard/dashboard_chart.dart b/lib/ui/dashboard/dashboard_chart.dart index 9ae39dd8d51..e4a849ba8be 100644 --- a/lib/ui/dashboard/dashboard_chart.dart +++ b/lib/ui/dashboard/dashboard_chart.dart @@ -43,6 +43,21 @@ class DashboardChart extends StatefulWidget { class _DashboardChartState extends State { String? _selected; int _selectedIndex = 0; + late ScrollController _controller; + + @override + void initState() { + super.initState(); + + _controller = ScrollController(); + } + + @override + void dispose() { + _controller.dispose(); + + super.dispose(); + } void _onSelectionChanged(charts.SelectionModel model) { if (widget.onDateSelected == null) { @@ -139,82 +154,86 @@ class _DashboardChartState extends State { Divider(height: 1.0), LimitedBox( maxHeight: settings.enableComparison ? 122 : 102, - child: ListView( - shrinkWrap: true, - scrollDirection: Axis.horizontal, - children: widget.data!.map((dataGroup) { - final int index = widget.data!.indexOf(dataGroup); - final bool isSelected = index == _selectedIndex; - final bool isIncrease = - dataGroup.periodTotal > dataGroup.previousTotal; - final String changeAmount = (isIncrease ? '+' : '') + - formatNumber( - dataGroup.periodTotal - dataGroup.previousTotal, - context, - currencyId: widget.currencyId)!; - final changePercent = (isIncrease ? '+' : '') + - formatNumber( - dataGroup.periodTotal != 0 && - dataGroup.previousTotal != 0 - ? round( - (dataGroup.periodTotal - - dataGroup.previousTotal) / - dataGroup.previousTotal * - 100, - 2) - : 0.0, - context, - formatNumberType: FormatNumberType.percent, - currencyId: widget.currencyId)!; - final String changeString = dataGroup.periodTotal == 0 || - dataGroup.previousTotal == 0 || - dataGroup.periodTotal == dataGroup.previousTotal - ? (settings.enableComparison ? ' ' : '') - : '$changeAmount ($changePercent)'; + child: Scrollbar( + controller: _controller, + child: ListView( + shrinkWrap: true, + scrollDirection: Axis.horizontal, + controller: _controller, + children: widget.data!.map((dataGroup) { + final int index = widget.data!.indexOf(dataGroup); + final bool isSelected = index == _selectedIndex; + final bool isIncrease = + dataGroup.periodTotal > dataGroup.previousTotal; + final String changeAmount = (isIncrease ? '+' : '') + + formatNumber( + dataGroup.periodTotal - dataGroup.previousTotal, + context, + currencyId: widget.currencyId)!; + final changePercent = (isIncrease ? '+' : '') + + formatNumber( + dataGroup.periodTotal != 0 && + dataGroup.previousTotal != 0 + ? round( + (dataGroup.periodTotal - + dataGroup.previousTotal) / + dataGroup.previousTotal * + 100, + 2) + : 0.0, + context, + formatNumberType: FormatNumberType.percent, + currencyId: widget.currencyId)!; + final String changeString = dataGroup.periodTotal == 0 || + dataGroup.previousTotal == 0 || + dataGroup.periodTotal == dataGroup.previousTotal + ? (settings.enableComparison ? ' ' : '') + : '$changeAmount ($changePercent)'; - return InkWell( - onTap: () { - setState(() { - _selectedIndex = index; - _selected = null; - }); - }, - child: Container( - color: isSelected ? state.accentColor : theme.cardColor, - padding: EdgeInsets.only( - left: 16, top: 16, right: 32, bottom: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(localization!.lookup(dataGroup.name), - style: theme.textTheme.titleLarge!.copyWith( - color: isSelected ? Colors.white : null, - )), - SizedBox(height: 4), - Text( - formatNumber(dataGroup.periodTotal, context, - currencyId: widget.currencyId)!, - style: theme.textTheme.headlineSmall!.copyWith( - color: isSelected ? Colors.white : null)), - SizedBox(height: 4), - changeString.isNotEmpty - ? Text( - changeString, - style: TextStyle( - fontSize: 16, - color: isSelected - ? Colors.white - : (isIncrease - ? Colors.green - : Colors.red), - ), - ) - : SizedBox(), - ], + return InkWell( + onTap: () { + setState(() { + _selectedIndex = index; + _selected = null; + }); + }, + child: Container( + color: isSelected ? state.accentColor : theme.cardColor, + padding: EdgeInsets.only( + left: 16, top: 16, right: 32, bottom: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(localization!.lookup(dataGroup.name), + style: theme.textTheme.titleLarge!.copyWith( + color: isSelected ? Colors.white : null, + )), + SizedBox(height: 4), + Text( + formatNumber(dataGroup.periodTotal, context, + currencyId: widget.currencyId)!, + style: theme.textTheme.headlineSmall!.copyWith( + color: isSelected ? Colors.white : null)), + SizedBox(height: 4), + changeString.isNotEmpty + ? Text( + changeString, + style: TextStyle( + fontSize: 16, + color: isSelected + ? Colors.white + : (isIncrease + ? Colors.green + : Colors.red), + ), + ) + : SizedBox(), + ], + ), ), - ), - ); - }).toList(), + ); + }).toList(), + ), ), ), Divider(height: 1.0), diff --git a/lib/ui/dashboard/dashboard_panels.dart b/lib/ui/dashboard/dashboard_panels.dart index 30de5731b91..03cf072b6e1 100644 --- a/lib/ui/dashboard/dashboard_panels.dart +++ b/lib/ui/dashboard/dashboard_panels.dart @@ -558,6 +558,10 @@ class DashboardPanels extends StatelessWidget { currentQuoteData[1], DashboardUISettings.FIELD_UNAPPROVED_QUOTES: currentQuoteData[2], + DashboardUISettings.FIELD_INVOICED_QUOTES: + currentQuoteData[3], + DashboardUISettings.FIELD_INVOICE_PAID_QUOTES: + currentQuoteData[4], DashboardUISettings.FIELD_LOGGED_TASKS: currentTaskData[0], DashboardUISettings.FIELD_INVOICED_TASKS: currentTaskData[1], @@ -587,6 +591,10 @@ class DashboardPanels extends StatelessWidget { previousQuoteData[1], DashboardUISettings.FIELD_UNAPPROVED_QUOTES: previousQuoteData[2], + DashboardUISettings.FIELD_INVOICED_QUOTES: + previousQuoteData[3], + DashboardUISettings.FIELD_INVOICE_PAID_QUOTES: + previousQuoteData[4], DashboardUISettings.FIELD_LOGGED_TASKS: currentTaskData[0], DashboardUISettings.FIELD_INVOICED_TASKS: previousTaskData[1], diff --git a/lib/utils/i18n.dart b/lib/utils/i18n.dart index cc045554a56..1fbff80cd9f 100644 --- a/lib/utils/i18n.dart +++ b/lib/utils/i18n.dart @@ -18,7 +18,9 @@ mixin LocalizationsProvider on LocaleCodeAware { static final Map> _localizedValues = { 'en': { // STARTER: lang key - do not remove comment - 'directory_does_not_exist': +'total_invoiced_quotes': 'Invoiced Quotes', + 'total_invoice_paid_quotes': 'Invoice Paid Quotes', + 'directory_does_not_exist': 'The download directory does not exist :value', 'user_logged_in_notification': 'User Logged in Notification', 'user_logged_in_notification_help': @@ -109904,7 +109906,16 @@ mixin LocalizationsProvider on LocaleCodeAware { _localizedValues[localeCode]!['directory_does_not_exist'] ?? _localizedValues['en']!['directory_does_not_exist']!; -// STARTER: lang field - do not remove comment +String get totalInvoicedQuotes => + _localizedValues[localeCode]!['total_invoiced_quotes'] ?? + _localizedValues['en']!['total_invoiced_quotes']!; + +String get totalInvoicePaidQuotes => + _localizedValues[localeCode]!['total_invoice_paid_quotes'] ?? + _localizedValues['en']!['total_invoice_paid_quotes']!; + + + // STARTER: lang field - do not remove comment String lookup(String? key) { final lookupKey = toSnakeCase(key);